September 13th, 2024

Goal

Revise the codebase to follow the Model-View-Controller (MVC) architecture. Configure the application to direct users to the Main window after the database path has been set.

Hypothesis

If the codebase fully adopts the Model-View-Controller (MVC) architecture, then it will improve the separation of concerns and enhance maintainability.

If the application directs the users to the Main window after the database path has been set, then it will improve the user experience by streamlining the workflow.

Expected Results

Results

An oversight in my initial approach was assuming that the Model-View-Controller (MVC) structure only applied at the folder and file level. In reality, the MVC architecture must be implemented at the code level as well. This means that for each window in the application, there must be a corresponding set of files responsible for the view, controller, and model. For example, the Startup window currently managed by StartupWindow.py needs to be divided into three files: StartupWindowView.py, StartupWindowController.py, and StartupWindowModel.py, each placed in the appropriate folder according to its role. Currently, the Startup, Main, New Genome, and NCBI windows have been divided into their respective subfiles following this structure. However, I am facing some bugs with the functionality of the NCBI window, which I plan to resolve by the end of this week. I will also make sure the other windows are divided into their respective files.

One area that could benefit from improvement is standardizing the naming convention for the components in the .ui files. This would make it easier to locate and manage the UI elements. For example, on the Main window, the button that directs users to the Population Analysis window is named populationAnalysis_button, while the button to view targets is labeled pushButton_ViewTargets. In this case, we could adopt a more uniform convention, such as buttonPopulationAnalysis and buttonViewTargets. I plan to thoroughly modify the UI elements following this naming convention.

Another optimization to improve the user workflow is removing the NCBI navigation window that prompts the user when a file has been successfully downloaded to the CASPERdb directory. Instead of using an additional pop-up window, the NCBI window will display a message that reads: “Download(s) Complete. Press back to go to the Main Window.” This change will eliminate the need for an extra pop-up while maintaining transparency about the process.

Next Steps

My next steps are to complete dividing the code files into their respective subfiles according to the Model-View-Controller structure. The remaining windows that still need to be divided are New Endonuclease, Multitargeting Analysis, Population Analysis, View Targets, and Combine Files.

Another important goal is to expand CASPER's ability to fetch data files from sources other than NCBI, and to allow users to upload their own files for use in CASPER. This is another area that I will be looking at and experimenting with.

Containerizing the development environment using Docker is also on the agenda, as suggested by David. This will simplify the process for future developers to quickly set up the environment on their machines.

Files changed (63) hide show
  1. .gitignore +4 -0
  2. OffTargetFolder/OT_Lin +0 -0
  3. OffTargetFolder/OT_Mac +0 -0
  4. OffTargetFolder/OT_Win.exe +0 -0
  5. OffTargetFolder/sqlite3.dll +0 -0
  6. SeqFinderFolder/Casper_Seq_Finder_Lin +0 -0
  7. SeqFinderFolder/Casper_Seq_Finder_Mac +0 -0
  8. SeqFinderFolder/Casper_Seq_Finder_Win.exe +0 -0
  9. SeqFinderFolder/sqlite3.dll +0 -0
  10. assets/dark_mode.png +0 -0
  11. assets/light_mode.png +0 -0
  12. assets/{CASPER-logo.jpg → startup_image.jpg} +0 -0
  13. config/config.yml +8 -0
  14. controllers/CoTargeting.py +0 -139
  15. controllers/OffTarget.py +0 -277
  16. controllers/Results.py +0 -1766
  17. controllers/multitargeting.py +0 -825
  18. controllers/ncbi.py +0 -915
  19. controllers/populationAnalysis.py +0 -929
  20. controllers/scoring_window.py +0 -369
  21. scripts/mac.spec → mac.spec +20 -14
  22. main.py +0 -91
  23. models/CSPRparser.py +0 -115
  24. models/GlobalSettings.py +0 -15
  25. ui/CASPER_main.ui +0 -1262
  26. ui/NewGenome.ui +0 -1080
  27. ui/annotation_details.ui +0 -376
  28. ui/closing_window.ui +0 -136
  29. ui/cotargeting.ui +0 -173
  30. ui/export_tool.ui +0 -264
  31. ui/filter_options.ui +0 -223
  32. ui/generate_library.ui +0 -731
  33. ui/loading.ui +0 -60
  34. ui/loading_data_form.ui +0 -129
  35. ui/mt.ui +0 -553
  36. ui/multitargeting_sql_settings.ui +0 -149
  37. ui/multitargeting_stats.ui +0 -227
  38. ui/name_form.ui +0 -46
  39. ui/ncbi.ui +0 -494
  40. ui/ncbi_nav_page.ui +0 -172
  41. ui/ncbi_rename_window.ui +0 -121
  42. ui/newendonuclease.ui +0 -816
  43. ui/newgenomenavigationpage.ui +0 -184
  44. ui/off_target.ui +0 -394
  45. ui/pop.ui +0 -425
  46. ui/results.ui +0 -584
  47. ui/scoring_window.ui +0 -179
  48. ui/startupCASPER.ui +0 -276
  49. utils/Algorithms.py +0 -160
  50. utils/ui.py +0 -113
  51. utils/web.py +0 -17
  52. views/AnnotationParser.py +0 -429
  53. views/AnnotationWindow.py +0 -125
  54. views/CMainWindow.py +0 -1000
  55. views/GenBankParse.py +0 -82
  56. views/NewEndonuclease.py +0 -228
  57. views/NewGenome.py +0 -705
  58. views/StartupWindow.py +0 -255
  59. views/annotation_functions.py +0 -47
  60. views/closingWin.py +0 -73
  61. views/export_tool.py +0 -259
  62. views/generateLib.py +0 -662
  63. views/genomeBrowser.py +0 -154
.gitignore CHANGED
@@ -26,3 +26,7 @@ CASPERinfo
26
 
27
  # Operating system specific files
28
  .DS_Store
 
 
 
 
 
26
 
27
  # Operating system specific files
28
  .DS_Store
29
+
30
+ # PyInstaller files
31
+ dist/
32
+ build/
OffTargetFolder/OT_Lin DELETED
Binary file
 
OffTargetFolder/OT_Mac DELETED
Binary file
 
OffTargetFolder/OT_Win.exe DELETED
Binary file
 
OffTargetFolder/sqlite3.dll DELETED
Binary file
 
SeqFinderFolder/Casper_Seq_Finder_Lin DELETED
Binary file
 
SeqFinderFolder/Casper_Seq_Finder_Mac DELETED
Binary file
 
SeqFinderFolder/Casper_Seq_Finder_Win.exe DELETED
Binary file
 
SeqFinderFolder/sqlite3.dll DELETED
Binary file
 
assets/dark_mode.png ADDED
Binary file
 
assets/light_mode.png ADDED
Binary file
 
assets/{CASPER-logo.jpg → startup_image.jpg} RENAMED
File without changes
config/config.yml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ paths:
2
+ ui: ui
3
+ controllers: controllers
4
+ assets: assets
5
+ casper_info: CASPERinfo
6
+
7
+ algorithms:
8
+ - Azimuth 2.0
controllers/CoTargeting.py DELETED
@@ -1,139 +0,0 @@
1
- from PyQt5 import QtWidgets, Qt, QtGui, QtCore, uic
2
- import models.GlobalSettings as GlobalSettings
3
- import traceback
4
- import math
5
- from utils.ui import show_message, show_error, scale_ui, center_ui
6
-
7
- logger = GlobalSettings.logger
8
-
9
- ######################################################
10
- # This class is a window that lets the user select which endonucleases to co-target with
11
- # inputs are from the user and from results
12
- # from results: the organism name and the list of endonucleases for that organism
13
- # from user: which endonucleases to co-target
14
- ######################################################
15
- class CoTargeting(QtWidgets.QMainWindow):
16
- def __init__(self, path):
17
- try:
18
- super(CoTargeting, self).__init__()
19
- uic.loadUi(GlobalSettings.appdir + 'ui/cotargeting.ui', self)
20
- self.setWindowIcon(QtGui.QIcon(GlobalSettings.appdir + "cas9image.ico"))
21
- self.setWindowTitle("Co-targeting")
22
-
23
- self.endo_table.setColumnCount(1) # hardcoded because there will always be 1 columns
24
- self.endo_table.setShowGrid(True)
25
- self.endo_table.setHorizontalHeaderLabels("Endonuclease;".split(";"))
26
- self.endo_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
27
- self.endo_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
28
- self.endo_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
29
- self.endo_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch) #Ensures last column goes to the edge of table
30
-
31
- self.info_path = path
32
-
33
- self.cancel_button.clicked.connect(self.cancel_function)
34
- self.submit_button.clicked.connect(self.submission_function)
35
-
36
- scale_ui(self, custom_scale_width=450, custom_scale_height=375)
37
-
38
- except Exception as e:
39
- show_error("Error initializing CoTargeting class.", e)
40
-
41
- # launches the window
42
- # it is expecting endo_choices in the form of a list, and the orgName in the form of a string
43
- # it sets the organism name, and sets the table as well
44
- def launch(self, endo_choices, orgName):
45
- try:
46
- self.orgName.setText(orgName)
47
- setTableList = list()
48
- # only get the endo choices that were original
49
- for item in endo_choices:
50
- checkList = item.split(",")
51
- if len(checkList) == 1 and "|" not in item: #Prevent cotarget endos from being added back in
52
- setTableList.append(item)
53
-
54
- # go through and set each table item, but also set the row count
55
- self.endo_table.setRowCount(len(setTableList))
56
- loopCount = 0
57
- for item in setTableList:
58
- tabWidget = QtWidgets.QTableWidgetItem(item)
59
- self.endo_table.setItem(loopCount, 0, tabWidget)
60
- loopCount += 1
61
- self.endo_table.resizeColumnsToContents()
62
-
63
- center_ui(self)
64
-
65
- self.show()
66
- self.activateWindow()
67
- except Exception as e:
68
- show_error("Error in launch() in CoTargeting.", e)
69
-
70
- # it clears the table, sets the organism to nothing, and hides the window
71
- def cancel_function(self):
72
- try:
73
- self.endo_table.clearContents()
74
- self.endo_table.setRowCount(0)
75
- self.orgName.setText("")
76
- self.hide()
77
- except Exception as e:
78
- show_error("Error in cancel_function() in CoTargeting.", e)
79
-
80
- # this is the submission function.
81
- # it makes sure the user selects at least 2 endonucleases
82
- # then it goes through and returns the endonucleases selected
83
- # once it gets those, it then calls a function in Results that repopulates the table correctly
84
- def submission_function(self):
85
- try:
86
- #get endo data from CASPERinfo
87
- self.Endos = {}
88
- f = open(GlobalSettings.appdir + 'CASPERinfo')
89
- while True:
90
- line = f.readline()
91
- if line.startswith('ENDONUCLEASES'):
92
- while True:
93
- line = f.readline()
94
- if (line[0] == "-"):
95
- break
96
- line_tokened = line.split(";")
97
- endo = line_tokened[0]
98
- self.Endos[endo] = ([line_tokened[2], line_tokened[3], line_tokened[4]],line_tokened[5])
99
- break
100
- f.close()
101
-
102
- # set the selected_list, and make sure they select at least 2 endonucleases
103
- selected_list = self.endo_table.selectedItems()
104
- if len(selected_list) <= 1:
105
- show_message(
106
- fontSize=12,
107
- icon=QtWidgets.QMessageBox.Icon.Critical,
108
- title="Nothing Selected",
109
- message="No endonucleases selected. Please select at least 2 endonucleases"
110
- )
111
- return
112
-
113
- # go through and get which endonuclease's have been selected
114
- ret_endo_list = list()
115
- for i in range(self.endo_table.rowCount()):
116
- if self.endo_table.item(i, 0).isSelected():
117
- ret_endo_list.append(self.endo_table.item(i, 0).text())
118
-
119
- #invalid_flag = False
120
- for endo1 in ret_endo_list:
121
- for endo2 in ret_endo_list:
122
- if endo1 == endo2:
123
- continue
124
- endo1_len = sum([int(x) for x in self.Endos[endo1][0]])
125
- endo2_len = sum([int(x) for x in self.Endos[endo2][0]])
126
- if endo1_len != endo2_len or self.Endos[endo1][1] != self.Endos[endo2][1]: # If endonucleases don't have the same length gRNA or don't have the same directionality, throw an error
127
- show_message(
128
- fontSize=12,
129
- icon=QtWidgets.QMessageBox.Icon.Critical,
130
- title="Invalid Endonucleases",
131
- message="The selected endonucleases are not compatible."
132
- )
133
- return
134
-
135
- GlobalSettings.mainWindow.Results.co_target_endo_list = ret_endo_list
136
- GlobalSettings.mainWindow.Results.populate_cotarget_table()
137
- self.cancel_function()
138
- except Exception as e:
139
- show_error("Error in submission_function() in CoTargeting.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
controllers/OffTarget.py DELETED
@@ -1,277 +0,0 @@
1
- import os, platform
2
- from PyQt5 import QtWidgets, uic, QtCore, QtGui, Qt
3
- from functools import partial
4
- import models.GlobalSettings as GlobalSettings
5
- from utils.ui import show_message, show_error, scale_ui, center_ui
6
-
7
- logger = GlobalSettings.logger
8
-
9
- class OffTarget(QtWidgets.QMainWindow):
10
- def __init__(self):
11
- try:
12
- super(OffTarget, self).__init__()
13
- uic.loadUi(GlobalSettings.appdir + 'ui/off_target.ui', self)
14
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
15
- self.setWindowTitle("Off-Target Analysis")
16
- self.progressBar.setMinimum(0)
17
- self.progressBar.setMaximum(100)
18
- self.progressBar.setValue(0)
19
- self.run_clicked = False
20
- self.Run.clicked.connect(self.run_analysis)
21
- # self.tolerancehorizontalSlider.valueChanged.connect(self.tol_change)
22
- # self.tolerancehorizontalSlider.setMaximum(100)
23
- # self.tolerancehorizontalSlider.setMinimum(0)
24
- self.tolerance = 0.0
25
-
26
- self.cancelButton.clicked.connect(self.exit)
27
- self.fill_data_dropdown()
28
- self.perc = False
29
- self.bool_temp = False
30
- self.running = False
31
- self.process = QtCore.QProcess()
32
- self.output_path = ''
33
-
34
- groupbox_style = """
35
- QGroupBox:title{subcontrol-origin: margin;
36
- left: 10px;
37
- padding: 0 5px 0 5px;}
38
- QGroupBox#Step1{border: 2px solid rgb(111,181,110);
39
- border-radius: 9px;
40
- font: bold 14pt 'Arial';
41
- margin-top: 10px;}"""
42
-
43
- self.Step1.setStyleSheet(groupbox_style)
44
- self.Step2.setStyleSheet(groupbox_style.replace("Step1", "Step2"))
45
- self.Step3.setStyleSheet(groupbox_style.replace("Step1", "Step3"))
46
-
47
- scale_ui(self, custom_scale_width=400, custom_scale_height=450)
48
-
49
- except Exception as e:
50
- show_error("Error initializing OffTarget class.", e)
51
-
52
- #copied from MT to fill in the chromo and endo dropdowns based on CSPR files user provided at the startup
53
- def fill_data_dropdown(self):
54
- try:
55
- try:
56
- self.EndocomboBox.diconnect()
57
- except:
58
- pass
59
- try:
60
- self.OrgcomboBox.diconnect()
61
- except:
62
- pass
63
-
64
- self.OrgcomboBox.clear()
65
- self.EndocomboBox.clear()
66
- self.mismatchcomboBox.clear()
67
-
68
- self.organisms_to_files = {}
69
- self.organisms_to_endos = {}
70
-
71
- #fill in chromosome and endo dropdowns
72
- onlyfiles = [f for f in os.listdir(GlobalSettings.CSPR_DB) if os.path.isfile(os.path.join(GlobalSettings.CSPR_DB , f))]
73
- self.orgsandendos = {}
74
- self.shortName = {}
75
- for file in onlyfiles:
76
- if file.find('.cspr') != -1:
77
- newname = file[0:-4]
78
- endo = newname[newname.rfind("_") + 1:-1]
79
- hold = open(file, 'r')
80
- buf = (hold.readline())
81
- hold.close()
82
- buf = str(buf)
83
- buf = buf.strip()
84
- species = buf.replace("GENOME: ", "")
85
-
86
- if species in self.organisms_to_files:
87
- self.organisms_to_files[species][endo] = [file, file.replace(".cspr", "_repeats.db")]
88
- else:
89
- self.organisms_to_files[species] = {}
90
- self.organisms_to_files[species][endo] = [file, file.replace(".cspr", "_repeats.db")]
91
-
92
- if species in self.organisms_to_endos:
93
- self.organisms_to_endos[species].append(endo)
94
- else:
95
- self.organisms_to_endos[species] = [endo]
96
- if self.OrgcomboBox.findText(species) == -1:
97
- self.OrgcomboBox.addItem(species)
98
-
99
- # fill in endos dropdown based on current organism
100
- endos = self.organisms_to_endos[str(self.OrgcomboBox.currentText())]
101
- self.EndocomboBox.addItems(endos)
102
- self.OrgcomboBox.currentIndexChanged.connect(self.update_endos)
103
- self.EndocomboBox.currentIndexChanged.connect(self.change_endos)
104
-
105
- # update file names for current org/endo combo
106
- self.cspr_file = self.organisms_to_files[str(self.OrgcomboBox.currentText())][endos[0]][0]
107
- self.db_file = self.organisms_to_files[str(self.OrgcomboBox.currentText())][endos[0]][1]
108
-
109
- #fill in Max Mismatch dropdown
110
- mismatch_list = ['1','2','3','4','5','6','7','8','9','10']
111
- self.mismatchcomboBox.addItems(mismatch_list)
112
- self.mismatchcomboBox.setCurrentIndex(3) ### Max number of mismatches is 4 by default
113
- except Exception as e:
114
- show_error("Error in fill_data_dropdown() in OffTarget.", e)
115
-
116
- def change_endos(self):
117
- try:
118
- #update file names based on current org/endo combo
119
- self.cspr_file = self.organisms_to_files[str(self.OrgcomboBox.currentText())][str(self.EndocomboBox.currentText())][0]
120
- self.db_file = self.organisms_to_files[str(self.OrgcomboBox.currentText())][str(self.EndocomboBox.currentText())][1]
121
- except Exception as e:
122
- show_error("Error in change_endos() in OffTarget.", e)
123
-
124
- def update_endos(self):
125
- try:
126
- #try to disconnect index changed signal on endo dropdown if there is one
127
- try:
128
- self.EndocomboBox.currentIndexChanged.disconnect()
129
- except:
130
- pass
131
-
132
- #clear endo dropdown and fill in with endos relative to the current organism
133
- self.EndocomboBox.clear()
134
- endos = self.organisms_to_endos[str(self.OrgcomboBox.currentText())]
135
- self.EndocomboBox.addItems(endos)
136
- self.cspr_file = self.organisms_to_files[str(self.OrgcomboBox.currentText())][endos[0]][0]
137
- self.db_file = self.organisms_to_files[str(self.OrgcomboBox.currentText())][endos[0]][1]
138
-
139
- #reconnect index changed signal on endo dropdown
140
- self.EndocomboBox.currentIndexChanged.connect(self.change_endos)
141
- except Exception as e:
142
- show_error("Error in update_endos() in OffTarget.", e)
143
-
144
- #tolerance slider / entry box. Allows for slider to update, or the user to input in text box
145
- # def tol_change(self):
146
- # try:
147
- # if(self.tolerance == float(self.tolerancelineEdit.text())):
148
- # self.tolerance = self.tolerancehorizontalSlider.value() / 100 * 0.5
149
- # self.tolerance = round(self.tolerance, 3)
150
- # self.tolerancelineEdit.setText(str(self.tolerance))
151
- # else:
152
- # self.tolerance = float(self.tolerancelineEdit.text())
153
- # self.tolerance = round(self.tolerance, 3)
154
- # self.tolerancehorizontalSlider.setValue(round(self.tolerance/0.5 * 100))
155
- # except Exception as e:
156
- # logger.critical("Error in tol_change() in OffTarget.")
157
- # logger.critical(e)
158
- # logger.critical(traceback.format_exc())
159
- # exit(-1)
160
-
161
- #run button linked to run_analysis, which is linked to the run button
162
- def run_command(self):
163
- try:
164
- output_file_name = self.outputFileName.text().strip()
165
- save_internally = self.outputCheckBox.isChecked()
166
- if not output_file_name and not save_internally:
167
- show_message(
168
- fontSize=self.fontSize,
169
- icon=QtWidgets.QMessageBox.Icon.Warning,
170
- title="Input Error",
171
- message="Please enter a valid output file name."
172
- )
173
- return
174
-
175
- if save_internally:
176
- full_output_path = os.path.join(GlobalSettings.appdir, 'local/local_output.txt')
177
- else:
178
- full_output_path = os.path.join(GlobalSettings.CSPR_DB, output_file_name)
179
- if os.path.isfile(full_output_path):
180
- show_message(
181
- fontSize=self.fontSize,
182
- icon=QtWidgets.QMessageBox.Icon.Critical,
183
- title="Error",
184
- message="Output file already exists. Please choose a new output file name."
185
- )
186
- return
187
-
188
- self.tolerance = self.toleranceSpinBox.value()
189
- self.perc = False
190
- self.bool_temp = False
191
- self.running = False
192
-
193
- app_path = GlobalSettings.appdir.replace('\\','/')
194
- exe_path = os.path.join(app_path, 'OffTargetFolder', 'OT_Win.exe' if platform.system() == 'Windows' else 'OT_Lin' if platform.system() == 'Linux' else 'OT_Mac')
195
- data_path = os.path.join(app_path, 'OffTargetFolder', 'temp.txt')
196
- endo = self.EndocomboBox.currentText()
197
- cspr_path = os.path.join(GlobalSettings.CSPR_DB, self.cspr_file)
198
- db_path = os.path.join(GlobalSettings.CSPR_DB, self.db_file)
199
- CASPER_info_path = os.path.join(app_path, 'CASPERinfo')
200
- num_of_mismatches = int(self.mismatchcomboBox.currentText())
201
- hsu = GlobalSettings.mainWindow.Results.endo_data[self.EndocomboBox.currentText()][2]
202
-
203
- self.output_path = ' "' + full_output_path + '"'
204
-
205
- cmd = f'"{exe_path}" "{data_path}" "{endo}" "{cspr_path}" "{db_path}" "{full_output_path}" "{CASPER_info_path}" {num_of_mismatches} {self.tolerance} {"TRUE" if self.AVG.isChecked() else "FALSE"} {"FALSE" if self.AVG.isChecked() else "TRUE"} "{hsu}"'
206
- cmd = cmd.replace('/', '\\') if platform.system() == 'Windows' else cmd
207
-
208
- def finished():
209
- self.running = False
210
- self.run_clicked = True
211
- self.progressBar.setValue(100)
212
-
213
- #used to know when data is ready to read from stdout
214
- def dataReady():
215
- #filter the data from stdout, bools used to know when the .exe starts outputting the progress
216
- #percentages to be able to type cast them as floats and update the progress bar. Also, must
217
- #split the input read based on '\n\ characters since the stdout read can read multiple lines at
218
- #once and is all read in as raw bytes
219
- raw_data = self.process.readAllStandardOutput().data().decode()
220
- lines = raw_data.replace('\r', '').split('\n')
221
- for line in lines:
222
- if "Parsing Input Arguments" in line:
223
- self.progressBar.setValue(10)
224
- elif "Loading data for algorithm" in line:
225
- self.progressBar.setValue(25)
226
- elif "Running OffTarget Analysis" in line:
227
- self.progressBar.setValue(50)
228
-
229
- #connect QProcess to the dataReady func, and finished func, reset progressBar only if the outputfile name
230
- #given does not already exist
231
- self.process.readyReadStandardOutput.connect(partial(dataReady))
232
- self.process.readyReadStandardError.connect(partial(dataReady))
233
- self.progressBar.setValue(1)
234
- QtCore.QTimer.singleShot(100, partial(self.process.start, cmd))
235
- self.process.finished.connect(finished)
236
- except Exception as e:
237
- show_error("Error in run_command() in OffTarget.", e)
238
-
239
- def run_analysis(self):
240
- try:
241
- #make sure an analysis isn't already running before starting
242
- if(self.running == False):
243
- self.running = True
244
- self.run_command()
245
- except Exception as e:
246
- show_error("Error in run_analysis() in OffTarget.", e)
247
-
248
- #exit linked to user clicking cancel, resets bools, and kills process if one was running
249
- def exit(self):
250
- try:
251
- self.perc = False
252
- self.bool_temp = False
253
- self.running = False
254
- self.process.kill()
255
- self.hide()
256
-
257
- local_output_path = os.path.join(GlobalSettings.appdir, 'local/local_output.txt')
258
-
259
- if os.path.exists(local_output_path):
260
- os.remove(local_output_path)
261
- print("Local output file deleted successfully.")
262
- else:
263
- print("Local output file does not exist.")
264
- except Exception as e:
265
- show_error("Error in exit() in OffTarget.", e)
266
-
267
- #closeEvent linked to user pressing the x in the top right of windows, resets bools, and
268
- #kills process if there was one running
269
- def closeEvent(self, event):
270
- try:
271
- self.process.kill()
272
- self.perc = False
273
- self.bool_temp = False
274
- self.running = False
275
- event.accept()
276
- except Exception as e:
277
- show_error("Error in closeEvent() in OffTarget.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
controllers/Results.py DELETED
@@ -1,1766 +0,0 @@
1
- from utils.Algorithms import get_table_headers
2
- from PyQt5 import QtWidgets, uic, QtCore, QtGui, Qt
3
- from Bio.Seq import Seq
4
- from Bio import SeqIO
5
- from models.CSPRparser import CSPRparser
6
- import models.GlobalSettings as GlobalSettings
7
- import controllers.OffTarget as OffTarget
8
- import platform
9
- import traceback
10
- import math
11
- from controllers.scoring_window import Scoring_Window
12
- from utils.ui import scale_ui, center_ui
13
-
14
-
15
- #global logger
16
- logger = GlobalSettings.logger
17
-
18
- # =========================================================================================
19
- # CLASS NAME: Results
20
- # Inputs: Takes information from the main application window and displays the gRNA results
21
- # Outputs: The display of the gRNA results search
22
- # =========================================================================================
23
- class Results(QtWidgets.QMainWindow):
24
-
25
- def __init__(self, parent=None):
26
- try:
27
- super(Results, self).__init__(parent)
28
- uic.loadUi(GlobalSettings.appdir + 'ui/results.ui', self)
29
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
30
- self.setWindowTitle('Results')
31
- self.geneViewer.setReadOnly(True)
32
- self.curgene = ""
33
- self.dbpath = ""
34
- # Main Data container
35
- # Keys: Gene names
36
- # Values: #
37
- self.annotation_path = ""
38
- self.AllData = {}
39
- self.highlighted = {}
40
- self.co_target_endo_list = list()
41
- self.startpos = 0
42
- self.endpos = 0
43
- self.directory = ""
44
- self.inputtype = ""
45
- self.featureDict = dict() # dictionary passed into transfer_data
46
- self.featureNTDict = dict() #dictionary passed into transfer_data, same key as featureDict, but hols the NTSEQ
47
- self.chromDict = dict() # Initialize dictionary for storing chromosome lengths, same key as featureDict
48
- self.switcher = [1,1,1,1,1,1,1,1] # for keeping track of where we are in the sorting clicking for each column
49
-
50
- # Initialize Filter Options Object
51
- self.filter_options = Filter_Options()
52
-
53
- # Initialize Scoring Window Object
54
- self.scoring_window = Scoring_Window()
55
-
56
- # Target Table settings #
57
- self.targetTable.setColumnCount(8) #
58
- self.targetTable.setShowGrid(False)
59
- self.targetTable.setHorizontalHeaderLabels("Location;Endonuclease;Sequence;Strand;PAM;Score;Off-Target;Details".split(";"))
60
- self.targetTable.horizontalHeader().setSectionsClickable(True)
61
- self.targetTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
62
- self.targetTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
63
- self.targetTable.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
64
- self.targetTable.horizontalHeader().setSectionResizeMode(7, QtWidgets.QHeaderView.Stretch) #Ensures last column goes to the edge of table
65
- self.targetTable.horizontalHeader().setSectionResizeMode(7, QtWidgets.QHeaderView.Stretch) #Ensures last column goes to the edge of table
66
-
67
- self.back_button.clicked.connect(self.goBack)
68
- self.targetTable.horizontalHeader().sectionClicked.connect(self.table_sorting)
69
- self.off_target_button.clicked.connect(self.Off_Target_Analysis)
70
- self.cotargeting_button.clicked.connect(self.open_cotarget)
71
- self.displayGeneViewer.stateChanged.connect(self.checkGeneViewer)
72
- self.filter_options.cotarget_checkbox.stateChanged.connect(self.prep_cotarget_checkbox)
73
- self.highlight_gene_viewer_button.clicked.connect(self.highlight_gene_viewer)
74
- self.checkBoxSelectAll.stateChanged.connect(self.selectAll)
75
- self.filter_options_button.clicked.connect(self.show_filter_options)
76
- self.scoring_options_button.clicked.connect(self.show_scoring_window)
77
-
78
-
79
- self.change_start_end_button.clicked.connect(self.change_indices)
80
- self.reset_location_button.clicked.connect(self.reset_location)
81
- self.export_button.clicked.connect(self.open_export_tool)
82
-
83
- #self.targetTable.itemSelectionChanged.connect(self.item_select)
84
- self.filter_options.minScoreLine.setText("0")
85
-
86
- # Connecting the filters to the displayGeneData function
87
- self.filter_options.fivegseqCheckBox.stateChanged.connect(self.displayGeneData)
88
- self.filter_options.minScoreLine.textChanged.connect(self.displayGeneData)
89
-
90
- # Setting up the score filter:
91
- self.filter_options.scoreSlider.setMinimum(0)
92
- self.filter_options.scoreSlider.setMaximum(100)
93
- self.filter_options.scoreSlider.setTracking(False)
94
- self.filter_options.scoreSlider.valueChanged.connect(self.update_score_filter)
95
-
96
- #bool used to make sure only 1 instance of the OffTarget window is created
97
- self.first_boot = True
98
- #OTA is used to hold the row numbers of the items selected by user for OffTargetAnalysis
99
- #using this helps speed up updating the chart
100
- self.OTA = []
101
-
102
- self.clear_highlighted_guides_button.clicked.connect(self.clear_highlighted_guides)
103
-
104
- self.detail_output_list = []
105
- self.rows_and_seq_list = []
106
- self.seq_and_avg_list = []
107
- self.files_list = []
108
- self.mwfg = self.frameGeometry() ##Center window
109
- self.cp = QtWidgets.QDesktopWidget().availableGeometry().center() ##Center window
110
-
111
- groupbox_style = """
112
- QGroupBox:title{subcontrol-origin: margin;
113
- left: 10px;
114
- padding: 0 5px 0 5px;}
115
- QGroupBox#guide_viewer{border: 2px solid rgb(111,181,110);
116
- border-radius: 9px;
117
- margin-top: 10px;
118
- font: bold 14pt 'Arial';}"""
119
-
120
- self.guide_viewer.setStyleSheet(groupbox_style)
121
- self.guide_analysis.setStyleSheet(groupbox_style.replace("guide_viewer", "guide_analysis"))
122
- self.gene_viewer.setStyleSheet(groupbox_style.replace("guide_viewer", "gene_viewer"))
123
-
124
- self.get_endo_data()
125
-
126
- ### Make line edits only accept integers
127
- self.lineEditStart.setValidator(QtGui.QIntValidator())
128
- self.lineEditEnd.setValidator(QtGui.QIntValidator())
129
-
130
-
131
- #scale UI
132
- self.first_show = True
133
- self.scaleUI()
134
-
135
- except Exception as e:
136
- logger.critical("Error initializing results class.")
137
- logger.critical(e)
138
- logger.critical(traceback.format_exc())
139
- msgBox = QtWidgets.QMessageBox()
140
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
141
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
142
- msgBox.setWindowTitle("Fatal Error")
143
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
144
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
145
- msgBox.exec()
146
-
147
-
148
- exit(-1)
149
-
150
- #scale UI based on current screen
151
- def scaleUI(self):
152
- try:
153
- self.repaint()
154
- QtWidgets.QApplication.processEvents()
155
-
156
- screen = self.screen()
157
- dpi = screen.physicalDotsPerInch()
158
- width = screen.geometry().width()
159
- height = screen.geometry().height()
160
-
161
- # font scaling
162
- fontSize = 12
163
- self.fontSize = fontSize
164
- self.centralWidget().setStyleSheet("font: " + str(fontSize) + "pt 'Arial';")
165
-
166
- # CASPER header scaling
167
- fontSize = 30
168
- self.title.setStyleSheet("font: bold " + str(fontSize) + "pt 'Arial';")
169
-
170
- self.adjustSize()
171
-
172
- currentWidth = self.size().width()
173
- currentHeight = self.size().height()
174
-
175
- # window scaling
176
- # 1920x1080 => 850x750
177
- scaledWidth = int((width * 1250) / 1920)
178
- scaledHeight = int((height * 750) / 1080)
179
-
180
- if scaledHeight < currentHeight:
181
- scaledHeight = currentHeight
182
- if scaledWidth < currentWidth:
183
- scaledWidth = currentWidth
184
-
185
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
186
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
187
- x = centerPoint.x()
188
- y = centerPoint.y()
189
- x = x - (math.ceil(scaledWidth / 2))
190
- y = y - (math.ceil(scaledHeight / 2))
191
- self.setGeometry(x, y, scaledWidth, scaledHeight)
192
-
193
- self.repaint()
194
- QtWidgets.QApplication.processEvents()
195
- except Exception as e:
196
- logger.critical("Error in scaleUI() in results.")
197
- logger.critical(e)
198
- logger.critical(traceback.format_exc())
199
- msgBox = QtWidgets.QMessageBox()
200
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
201
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
202
- msgBox.setWindowTitle("Fatal Error")
203
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
204
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
205
- msgBox.exec()
206
-
207
-
208
- exit(-1)
209
-
210
- #center UI on current screen
211
- def centerUI(self):
212
- try:
213
- self.repaint()
214
- QtWidgets.QApplication.processEvents()
215
-
216
- # center window on current screen
217
- width = self.width()
218
- height = self.height()
219
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
220
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
221
- x = centerPoint.x()
222
- y = centerPoint.y()
223
- x = x - (math.ceil(width / 2))
224
- y = y - (math.ceil(height / 2))
225
- self.setGeometry(x, y, width, height)
226
-
227
- self.repaint()
228
- QtWidgets.QApplication.processEvents()
229
- except Exception as e:
230
- logger.critical("Error in centerUI() in results.")
231
- logger.critical(e)
232
- logger.critical(traceback.format_exc())
233
- msgBox = QtWidgets.QMessageBox()
234
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
235
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
236
- msgBox.setWindowTitle("Fatal Error")
237
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
238
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
239
- msgBox.exec()
240
-
241
-
242
- exit(-1)
243
-
244
- def get_endo_data(self):
245
- try:
246
- f = open(GlobalSettings.appdir + "CASPERinfo")
247
- self.endo_data = {}
248
- while True:
249
- line = f.readline()
250
- if line.startswith('ENDONUCLEASES'):
251
- while True:
252
- line = f.readline()
253
- line = line.replace("\n","")
254
- if (line[0] == "-"):
255
- break
256
- line_tokened = line.split(";")
257
- if len(line_tokened) == 10:
258
- endo = line_tokened[0]
259
- five_length = line_tokened[2]
260
- seed_length = line_tokened[3]
261
- three_length = line_tokened[4]
262
- prime = line_tokened[5]
263
- hsu = line_tokened[9]
264
- self.endo_data[endo] = [int(five_length) + int(three_length) + int(seed_length), prime, "MATRIX:" + hsu]
265
-
266
- break
267
- f.close()
268
- except Exception as e:
269
- logger.critical("Error in get_endo_data() in results.")
270
- logger.critical(e)
271
- logger.critical(traceback.format_exc())
272
- msgBox = QtWidgets.QMessageBox()
273
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
274
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
275
- msgBox.setWindowTitle("Fatal Error")
276
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
277
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
278
- msgBox.exec()
279
-
280
-
281
- exit(-1)
282
-
283
- # This function resets (turns off, then on) the selection of all the rows in the ViewTargets table.
284
- # For some reason this is necessary after adding values to the table through alternative scoring
285
- # (different on-target scoring or off-target), otherwise the export function will bug due to newly
286
- # added items being queued to the back of the list of self.targetTable.selectedItems(), instead of
287
- # where they belong at the end of each row.
288
- def reset_selection(self):
289
- rows = sorted(set(index.row() for index in self.targetTable.selectedIndexes())) # Find selected rows
290
- self.targetTable.clearSelection() # Clear the selection
291
- for row in rows: # For each selected row
292
- self.targetTable.selectRow(row) # Reselect each row
293
-
294
- # this function opens the export_tool window
295
- # first it makes sure that the user actually has some highlighted targets that they want exported
296
- def open_export_tool(self):
297
- try:
298
- self.reset_selection()
299
- select_items = self.targetTable.selectedItems()
300
- if len(select_items) <= 0:
301
- msgBox = QtWidgets.QMessageBox()
302
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
303
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
304
- msgBox.setWindowTitle("Nothing Selected")
305
- msgBox.setText("No targets were highlighted. Please highlight the targets you want to be exported to a CSV File!")
306
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
307
- msgBox.exec()
308
-
309
- return
310
- # now launch the window
311
- GlobalSettings.mainWindow.export_tool_window.launch(select_items,"vt")
312
- except Exception as e:
313
- logger.critical("Error in open_export_tool() in results.")
314
- logger.critical(e)
315
- logger.critical(traceback.format_exc())
316
- msgBox = QtWidgets.QMessageBox()
317
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
318
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
319
- msgBox.setWindowTitle("Fatal Error")
320
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
321
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
322
- msgBox.exec()
323
-
324
-
325
- exit(-1)
326
-
327
- def change_indices(self):
328
- try:
329
- ### Make sure the gene viewer is on
330
- if not self.displayGeneViewer.isChecked():
331
- msgBox = QtWidgets.QMessageBox()
332
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
333
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
334
- msgBox.setWindowTitle("Gene Viewer Error")
335
- msgBox.setText("Gene Viewer display is off! Please turn the Gene Viewer on in order to highlight the sequences selected")
336
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
337
- msgBox.exec()
338
-
339
- return
340
-
341
- ### Change the start and end values
342
- prevTuple = self.featureDict[self.curgene]
343
- tempTuple = (self.featureDict[self.curgene][0], int(self.lineEditStart.displayText())-1, int(self.lineEditEnd.displayText()))
344
-
345
- ### Make sure both indices are greater than 0
346
- if tempTuple[1]+1 <= 0 or tempTuple[2] <= 0:
347
- msgBox = QtWidgets.QMessageBox()
348
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
349
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
350
- msgBox.setWindowTitle("Invalid location indices.")
351
- msgBox.setText("Location indices cannot be negative or zero! Please set values larger than 0.")
352
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
353
- msgBox.exec()
354
-
355
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1))
356
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2]))
357
- self.reset_location()
358
- return
359
-
360
- ### Make sure start is less than stop
361
- if tempTuple[1] >= tempTuple[2]:
362
- msgBox = QtWidgets.QMessageBox()
363
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
364
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
365
- msgBox.setWindowTitle("Invalid location indices.")
366
- msgBox.setText("Start location must be less than stop location.")
367
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
368
- msgBox.exec()
369
-
370
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1))
371
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2]))
372
- self.reset_location()
373
- return
374
-
375
- ### Make sure that the difference between indicies is not too large
376
- if abs(tempTuple[1] - tempTuple[2]) > 50000:
377
- msgBox = QtWidgets.QMessageBox()
378
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
379
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
380
- msgBox.setWindowTitle("Sequence Too Long")
381
- msgBox.setText("The sequence is too long! Please choose indicies that will make the sequence less than 50,000!")
382
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
383
- msgBox.exec()
384
-
385
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1))
386
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2]))
387
- self.reset_location()
388
- return
389
-
390
- ### Make sure search is within chromosome range
391
- if int(tempTuple[2]) > self.chromDict[self.curgene]:
392
- msgBox = QtWidgets.QMessageBox()
393
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
394
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
395
- msgBox.setWindowTitle("Position Error: Region not in Chromosome")
396
- msgBox.setText(
397
- "The stop location is greater than the chromosome's length.")
398
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
399
- msgBox.exec()
400
-
401
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1))
402
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2]))
403
- self.reset_location()
404
- return
405
-
406
- sequence, chrom_len = self.sequence_finder(tempTuple) # Get the appropriate NT sequence
407
- self.geneViewer.setText(sequence) # Set the gene viewer to display the sequence
408
- except Exception as e:
409
- logger.critical("Error in change_indices() in results.")
410
- logger.critical(e)
411
- logger.critical(traceback.format_exc())
412
- msgBox = QtWidgets.QMessageBox()
413
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
414
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
415
- msgBox.setWindowTitle("Fatal Error")
416
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
417
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
418
- msgBox.exec()
419
-
420
-
421
- exit(-1)
422
-
423
- # this function listens for a stateChange in selectAllShown
424
- # if it is checked, it selects all shown
425
- # if it is unchecked, it deselects all shown
426
- # Note: it is a little buggy, possibly because when you change the minimum score it resets it all
427
- def selectAll(self):
428
- try:
429
- if self.checkBoxSelectAll.isChecked():
430
- self.targetTable.selectAll()
431
- else:
432
- self.targetTable.clearSelection()
433
- except Exception as e:
434
- logger.critical("Error in selectAll() in results.")
435
- logger.critical(e)
436
- logger.critical(traceback.format_exc())
437
- msgBox = QtWidgets.QMessageBox()
438
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
439
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
440
- msgBox.setWindowTitle("Fatal Error")
441
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
442
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
443
- msgBox.exec()
444
-
445
-
446
- exit(-1)
447
- ### This function resets gene viewer to the appropriate sequence
448
- def reset_location(self):
449
- try:
450
- if self.displayGeneViewer.isChecked():
451
- self.geneViewer.setText(self.featureNTDict[self.curgene])
452
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1))
453
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2]))
454
- else:
455
- msgBox = QtWidgets.QMessageBox()
456
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
457
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
458
- msgBox.setWindowTitle("Gene Viewer Error")
459
- msgBox.setText("Gene Viewer display is off! Please turn the Gene Viewer on in order to reset the locations")
460
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
461
- msgBox.exec()
462
- except Exception as e:
463
- logger.critical("Error in reset_location() in results.")
464
- logger.critical(e)
465
- logger.critical(traceback.format_exc())
466
- msgBox = QtWidgets.QMessageBox()
467
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
468
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
469
- msgBox.setWindowTitle("Fatal Error")
470
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
471
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
472
- msgBox.exec()
473
- exit(-1)
474
-
475
-
476
-
477
-
478
- # hightlights the sequences found in the gene viewer
479
- # highlighting should stay the exact same with fasta and genbank files, as this function only edits what
480
- # is currently in the gene viewer text table anyways
481
- def highlight_gene_viewer(self):
482
- try:
483
- # make sure gene viewer is enabled
484
- if not self.displayGeneViewer.isChecked():
485
- msgBox = QtWidgets.QMessageBox()
486
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
487
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
488
- msgBox.setWindowTitle("Gene Viewer Error")
489
- msgBox.setText("Gene Viewer display is off! Please turn the Gene Viewer on in order to highlight the sequences selected")
490
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
491
- msgBox.exec()
492
-
493
- return
494
-
495
- # variables needed
496
- cursor = self.geneViewer.textCursor()
497
- format = QtGui.QTextCharFormat()
498
- failed_guides = []
499
-
500
- # check and make sure still is actually highlighted!
501
- selectedList = self.targetTable.selectedItems()
502
- if len(selectedList) <= 0:
503
- msgBox = QtWidgets.QMessageBox()
504
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
505
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
506
- msgBox.setWindowTitle("Nothing Selected")
507
- msgBox.setText("No targets were highlighted. Please highlight the targets you want to be highlighted in the gene viewer!")
508
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
509
- msgBox.exec()
510
-
511
- return
512
- # this is the loop that actually goes in and highlights all the things
513
- for i in range(self.targetTable.rowCount()):
514
- if self.targetTable.item(i, 0).isSelected():
515
- # get the strand and sequence strings
516
- locationString = self.targetTable.item(i,0).text()
517
- strandString = self.targetTable.item(i, 3).text()
518
- sequenceString = self.targetTable.item(i, 2).text()
519
- printSequence = ""
520
- movementIndex = len(sequenceString)
521
- left_right = ""
522
- #print("Length of geneViewer: ", len(self.geneViewer.toPlainText()))
523
-
524
- if strandString == "+":
525
- format.setBackground(QtGui.QBrush(QtGui.QColor("green")))
526
- index = self.geneViewer.toPlainText().upper().find(str(sequenceString))
527
- if index != -1: # If gRNA is found in GeneViewer
528
- cursor.setPosition(index)
529
- for i in range(movementIndex): # Actually highlight the gRNA now
530
- cursor.movePosition(QtGui.QTextCursor.NextCharacter, 1)
531
- cursor.mergeCharFormat(format)
532
- else:
533
- failed_guides.append(sequenceString)
534
- continue
535
- else: # gRNA is on negative strand
536
- format.setBackground(QtGui.QBrush(QtGui.QColor("red")))
537
- index = self.geneViewer.toPlainText().upper().find(str(Seq(sequenceString).reverse_complement()))
538
- if index != -1: # If gRNA is found in GeneViewer
539
- cursor.setPosition(index)
540
- for i in range(movementIndex): # Actually highlight the gRNA now
541
- cursor.movePosition(QtGui.QTextCursor.NextCharacter, 1)
542
- cursor.mergeCharFormat(format)
543
- else:
544
- failed_guides.append(sequenceString)
545
- continue
546
-
547
- # if any of the sequences return 0 matches, show the user which ones were not found
548
- if len(failed_guides) > 0:
549
- msgBox = QtWidgets.QMessageBox()
550
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
551
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
552
- msgBox.setWindowTitle("Warning")
553
- msgBox.setText(
554
- "The following sequence(s) were not found in the Gene Viewer text:\n\t" + "\n".join(failed_guides))
555
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
556
- msgBox.exec()
557
-
558
- except Exception as e:
559
- logger.critical("Error in highlight_gene_viewer() in results.")
560
- logger.critical(e)
561
- logger.critical(traceback.format_exc())
562
- msgBox = QtWidgets.QMessageBox()
563
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
564
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
565
- msgBox.setWindowTitle("Fatal Error")
566
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
567
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
568
- msgBox.exec()
569
-
570
-
571
- exit(-1)
572
-
573
- # this function updates the gene viewer based on the user clicking 'display on'
574
- # if it is check marked, it displays the correct data
575
- # if it is un-marked, it hides the data
576
- def checkGeneViewer(self):
577
- try:
578
- if self.displayGeneViewer.isChecked():
579
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1))
580
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2]))
581
- self.geneViewer.setText(self.featureNTDict[self.curgene])
582
- elif not self.displayGeneViewer.isChecked():
583
- self.lineEditStart.clear()
584
- self.lineEditEnd.clear()
585
- self.geneViewer.clear()
586
- except Exception as e:
587
- logger.critical("Error in checkGeneViewer() in results.")
588
- logger.critical(e)
589
- logger.critical(traceback.format_exc())
590
- msgBox = QtWidgets.QMessageBox()
591
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
592
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
593
- msgBox.setWindowTitle("Fatal Error")
594
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
595
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
596
- msgBox.exec()
597
-
598
-
599
- exit(-1)
600
-
601
- # this function opens when the user clicks the CoTargeting button
602
- def open_cotarget(self):
603
- try:
604
- endo_list = list()
605
- if self.endonucleaseBox.count() <= 1:
606
- msgBox = QtWidgets.QMessageBox()
607
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
608
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
609
- msgBox.setWindowTitle("Not Enough Endonucleases")
610
- msgBox.setText(
611
- "There are not enough endonucleases with this organism. At least 2 endonucleases are required for this function. Use Analyze New Genome to create CSPR files with other endonucleases.")
612
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
613
- msgBox.exec()
614
-
615
- return
616
-
617
- for i in range(self.endonucleaseBox.count()):
618
- endo_list.append(self.endonucleaseBox.itemText(i))
619
-
620
- GlobalSettings.mainWindow.CoTargeting.launch(endo_list, GlobalSettings.mainWindow.orgChoice.currentText())
621
- except Exception as e:
622
- logger.critical("Error in open_cotarget() in results.")
623
- logger.critical(e)
624
- logger.critical(traceback.format_exc())
625
- msgBox = QtWidgets.QMessageBox()
626
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
627
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
628
- msgBox.setWindowTitle("Fatal Error")
629
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
630
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
631
- msgBox.exec()
632
-
633
-
634
- exit(-1)
635
-
636
- # this function goes through and calls transfer_data again.
637
- # Uses data from the mainWindow in Globalsettings, but that's because that info should not change
638
- # unless the user closes out of the Results window
639
- def changeEndonuclease(self):
640
- try:
641
- full_org = str(GlobalSettings.mainWindow.orgChoice.currentText())
642
- # organism = GlobalSettings.mainWindow.shortHand[full_org]
643
-
644
- endoChoice = self.endonucleaseBox.currentText().split("|")
645
-
646
- # make sure the user actually selects a new endonuclease
647
- if self.endo == endoChoice:
648
- msgBox = QtWidgets.QMessageBox()
649
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
650
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
651
- msgBox.setWindowTitle("Select a different Endonuclease")
652
- msgBox.setText(
653
- "Please be sure to select a different endonuclease!")
654
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
655
- msgBox.exec()
656
-
657
- return
658
-
659
- # enable the cotarget checkbox if needed
660
- if len(endoChoice) > 1:
661
- self.filter_options.cotarget_checkbox.setEnabled(True)
662
- self.filter_options.cotarget_checkbox.setChecked(0)
663
- else:
664
- self.filter_options.cotarget_checkbox.setEnabled(False)
665
- self.filter_options.cotarget_checkbox.setChecked(0)
666
- self.transfer_data(full_org, GlobalSettings.mainWindow.organisms_to_files[full_org], endoChoice, GlobalSettings.CSPR_DB, self.featureDict,
667
- self.featureNTDict, self.inputtype)
668
- except Exception as e:
669
- logger.critical("Error in changeEndonuclease() in results.")
670
- logger.critical(e)
671
- logger.critical(traceback.format_exc())
672
- msgBox = QtWidgets.QMessageBox()
673
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
674
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
675
- msgBox.setWindowTitle("Fatal Error")
676
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
677
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
678
- msgBox.exec()
679
-
680
-
681
- exit(-1)
682
-
683
- # Function that is used to set up the results page.
684
- # it calls get_targets, which in turn calls display data
685
- def transfer_data(self, org, org_files, endo, path, feature_dict, featureNTSeqDict, inputtype):
686
- try:
687
- # set all of the classes variables
688
- self.org = org
689
- self.org_files = org_files
690
- self.endo = endo
691
- self.directory = path
692
- self.comboBoxGene.clear()
693
- self.AllData.clear()
694
- self.featureDict =feature_dict
695
- self.featureNTDict = featureNTSeqDict
696
- self.inputtype = inputtype
697
-
698
- self.highlighted.clear()
699
- self.detail_output_list.clear()
700
- self.seq_and_avg_list.clear()
701
- self.rows_and_seq_list.clear()
702
- self.OTA.clear()
703
-
704
- for feature in feature_dict:
705
- if self.inputtype == "feature":
706
- detail_output1 = {}
707
- rows_and_seq2 = {}
708
- seq_and_avg3 = {}
709
- self.detail_output_list.append(detail_output1)
710
- self.seq_and_avg_list.append(seq_and_avg3)
711
- self.rows_and_seq_list.append(rows_and_seq2)
712
- self.comboBoxGene.addItem(feature)
713
- self.get_targets(feature, feature_dict[feature])
714
- if self.inputtype == "position":
715
- detail_output1 = {}
716
- rows_and_seq2 = {}
717
- seq_and_avg3 = {}
718
- self.detail_output_list.append(detail_output1)
719
- self.seq_and_avg_list.append(seq_and_avg3)
720
- self.rows_and_seq_list.append(rows_and_seq2)
721
- self.comboBoxGene.addItem(feature)
722
- self.get_targets(feature, feature_dict[feature])
723
- if self.inputtype == "sequence":
724
- detail_output1 = {}
725
- rows_and_seq2 = {}
726
- seq_and_avg3 = {}
727
- self.detail_output_list.append(detail_output1)
728
- self.seq_and_avg_list.append(seq_and_avg3)
729
- self.rows_and_seq_list.append(rows_and_seq2)
730
- self.comboBoxGene.addItem(feature)
731
- self.get_targets(feature, feature_dict[feature])
732
-
733
-
734
- # Enable the combobox to be toggled now that the data is in AllData
735
- self.comboBoxGene.currentTextChanged.connect(self.displayGeneData)
736
- self.first_boot = True
737
- except Exception as e:
738
- logger.critical("Error in transfer_data() in results.")
739
- logger.critical(e)
740
- logger.critical(traceback.format_exc())
741
- msgBox = QtWidgets.QMessageBox()
742
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
743
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
744
- msgBox.setWindowTitle("Fatal Error")
745
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
746
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
747
- msgBox.exec()
748
-
749
-
750
- exit(-1)
751
-
752
- def goBack(self):
753
- try:
754
- GlobalSettings.mainWindow.show()
755
- self.filter_options.cotarget_checkbox.setChecked(0)
756
- self.filter_options.hide()
757
- try:
758
- self.off_tar_win.hide()
759
- except:
760
- pass
761
- GlobalSettings.mainWindow.CoTargeting.hide()
762
- self.scoring_window.hide()
763
- self.hide()
764
-
765
- except Exception as e:
766
- logger.critical("Error in goBack() in results.")
767
- logger.critical(e)
768
- logger.critical(traceback.format_exc())
769
- msgBox = QtWidgets.QMessageBox()
770
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
771
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
772
- msgBox.setWindowTitle("Fatal Error")
773
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
774
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
775
- msgBox.exec()
776
-
777
-
778
- exit(-1)
779
-
780
- # called when the user hits 'gene viewer settings'
781
- def changeGeneViewerSettings(self):
782
- try:
783
- GlobalSettings.mainWindow.gene_viewer_settings.show()
784
- GlobalSettings.mainWindow.gene_viewer_settings.activateWindow()
785
- except Exception as e:
786
- logger.critical("Error in changeGeneViewerSettings() in results.")
787
- logger.critical(e)
788
- logger.critical(traceback.format_exc())
789
- msgBox = QtWidgets.QMessageBox()
790
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
791
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
792
- msgBox.setWindowTitle("Fatal Error")
793
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
794
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
795
- msgBox.exec()
796
-
797
-
798
- exit(-1)
799
-
800
- # this is the function that sets up the cotargeting.
801
- # it is called from the Cotargeting class, when the user hits submit
802
- # myBool is whether or not to change the endoChoice comboBox
803
- def populate_cotarget_table(self, myBool = True):
804
- try:
805
- try:
806
- self.endonucleaseBox.currentIndexChanged.disconnect()
807
- except:
808
- pass
809
-
810
- # make a string of the combination, separated by commas's
811
- endoBoxString = ""
812
- for i in range(len(self.co_target_endo_list)):
813
- if endoBoxString == "":
814
- endoBoxString = self.co_target_endo_list[i]
815
- else:
816
- endoBoxString = endoBoxString + '|' + self.co_target_endo_list[i]
817
-
818
- # put the new endoChoice at the beginning. This is the only way i could find to do it
819
- # get a list of all endo choices, and put the newest at the front
820
- endoBoxList = list()
821
- endoBoxList.append(endoBoxString)
822
- for i in range(self.endonucleaseBox.count()):
823
- if self.endonucleaseBox.itemText(i) not in endoBoxList: # Prevent duplicate entries
824
- endoBoxList.append(self.endonucleaseBox.itemText(i))
825
-
826
- # clear the current endo choices, and append the new order
827
- if myBool:
828
- self.endonucleaseBox.clear()
829
- for i in range(len(endoBoxList)):
830
- self.endonucleaseBox.addItem(endoBoxList[i])
831
-
832
- # enable the cotarget checkbox
833
- self.filter_options.cotarget_checkbox.setEnabled(True)
834
- self.filter_options.cotarget_checkbox.setChecked(0)
835
-
836
- self.endonucleaseBox.currentIndexChanged.connect(self.changeEndonuclease)
837
- # add it to the endoBox choices, and then call transfer_data
838
- self.transfer_data(self.org, self.org_files, self.co_target_endo_list, GlobalSettings.CSPR_DB, self.featureDict, self.featureNTDict,self.inputtype)
839
- except Exception as e:
840
- logger.critical("Error in populate_cotarget_table() in results.")
841
- logger.critical(e)
842
- logger.critical(traceback.format_exc())
843
- msgBox = QtWidgets.QMessageBox()
844
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
845
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
846
- msgBox.setWindowTitle("Fatal Error")
847
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
848
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
849
- msgBox.exec()
850
-
851
-
852
- exit(-1)
853
-
854
- # prep function for the checkbox for cotargeting
855
- # if the checkbox is checked, just go ahead and displayGeneData
856
- # if not, call populate_cotarget_table, as a reset to get all of the data there
857
- def prep_cotarget_checkbox(self):
858
- try:
859
- if self.filter_options.cotarget_checkbox.isChecked():
860
- self.displayGeneData()
861
- elif not self.filter_options.cotarget_checkbox.isChecked():
862
- self.populate_cotarget_table(myBool=False)
863
- except Exception as e:
864
- logger.critical("Error in prep_cotarget_checkbox() in results.")
865
- logger.critical(e)
866
- logger.critical(traceback.format_exc())
867
- msgBox = QtWidgets.QMessageBox()
868
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
869
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
870
- msgBox.setWindowTitle("Fatal Error")
871
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
872
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
873
- msgBox.exec()
874
-
875
-
876
- exit(-1)
877
-
878
- # Function grabs the information from the .cspr file and adds them to the AllData dictionary
879
- #changed to now call CSPRparser's function. Same function essentially, just cleaned up here
880
- def get_targets(self, genename, pos_tuple):
881
- try:
882
- #get the right files
883
- for endo in self.endo:
884
- if platform.system() == "Windows":
885
- file = self.directory + "\\" + self.org_files[endo][0]
886
- else:
887
- file = self.directory + "/" + self.org_files[endo][0]
888
-
889
- #create the parser, read the targets store it. then display the GeneData screen
890
- parser = CSPRparser(file)
891
-
892
- # if genename is not in the dict, make that spot into a list
893
- if genename not in self.AllData:
894
- self.AllData[genename] = list()
895
- # now append parser's data to it
896
- self.AllData[genename].append(parser.read_targets(genename, pos_tuple, endo))
897
-
898
- # for each list item
899
- for item in self.AllData[genename]:
900
- # for each tuple item
901
- for i in range(len(item)):
902
- self.highlighted[item[i][1]] = False
903
-
904
- # if the endo choice is greater than 1, call the combine
905
- if len(self.endo) > 1:
906
- self.combine_coTargets(genename)
907
- self.displayGeneData()
908
- except Exception as e:
909
- logger.critical("Error in get_targets() in results.")
910
- logger.critical(e)
911
- logger.critical(traceback.format_exc())
912
- msgBox = QtWidgets.QMessageBox()
913
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
914
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
915
- msgBox.setWindowTitle("Fatal Error")
916
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
917
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
918
- msgBox.exec()
919
-
920
-
921
- exit(-1)
922
-
923
- ###############################################################################################################
924
- # Main Function for updating the Table. Connected to all filter buttons and the Gene toggling of the combobox.
925
- ###############################################################################################################
926
- def displayGeneData(self):
927
- try:
928
- self.curgene = str(self.comboBoxGene.currentText()) # Gets the current gene
929
- # Creates the set object from the list of the current gene:
930
- if self.curgene=='' or len(self.AllData)<1:
931
- return
932
-
933
- subset_display = []
934
- # set the start and end numbers, as well as set the geneViewer text, if the displayGeneViewer is checked
935
- if self.displayGeneViewer.isChecked():
936
- self.lineEditStart.setText(str(self.featureDict[self.curgene][1]+1)) # Set start index for gene (Add 1 to account for Python indexing convention)
937
- self.lineEditEnd.setText(str(self.featureDict[self.curgene][2])) # Set end index for gene
938
- self.geneViewer.setText(self.featureNTDict[self.curgene]) # Get gene sequence
939
-
940
- # if this checkBox is checked, remove the single endo
941
- if self.filter_options.cotarget_checkbox.isChecked():
942
- gene = self.curgene
943
- self.remove_single_endo(gene)
944
-
945
- # Removing all sequences below minimum score and creating the set:
946
- # for each list item
947
- for item in self.AllData[self.curgene]:
948
- # for each tuple item
949
- for i in range(len(item)):
950
- if int(item[i][3]) > int(self.filter_options.minScoreLine.text()):
951
- # Removing all non 5' G sequences:
952
- if self.filter_options.fivegseqCheckBox.isChecked():
953
- if item[i][1].startswith("G"):
954
- subset_display.append(item[i])
955
- else:
956
- subset_display.append(item[i])
957
-
958
- self.targetTable.setRowCount(len(subset_display))
959
- index = 0
960
- #changed the number items to use setData so that sorting will work correctly
961
- #because before the numbers were interpretted as strings and not numbers
962
-
963
-
964
- ### Remove alternative scoring columns (Azimuth, etc.) when switching between genes or loading new data...this prevents carry-over of the wrong scores from previously scored genes
965
- ### One possible solution would be to add alternate scores to self.AllData, but I won't do that for now.
966
- header = get_table_headers(self.targetTable) # Returns headers of the target table
967
- num_cols = len(header) # Get number of columns
968
- col_indices = [header.index(x) for x in GlobalSettings.algorithms if x in header] # Returns the index(es) of the alternative scoring column(s) in the target table of View Targets window
969
- if len(col_indices) > 0: # If alternative scoring has been done
970
- for i in col_indices:
971
- self.targetTable.removeColumn(i)
972
-
973
- for item in subset_display:
974
- num = int(item[0])
975
- loc = QtWidgets.QTableWidgetItem()
976
- loc.setData(QtCore.Qt.EditRole, abs(num))
977
- seq = QtWidgets.QTableWidgetItem(item[1])
978
- strand = QtWidgets.QTableWidgetItem(str(item[4]))
979
- PAM = QtWidgets.QTableWidgetItem(item[2])
980
- num1 = int(item[3])
981
- endonuclease = QtWidgets.QTableWidgetItem(item[5])
982
- score = QtWidgets.QTableWidgetItem()
983
- score.setData(QtCore.Qt.EditRole, num1)
984
- self.targetTable.setItem(index, 0, loc)
985
- self.targetTable.setItem(index, 1, endonuclease)
986
- self.targetTable.setItem(index, 2, seq)
987
- self.targetTable.setItem(index, 3, strand)
988
- self.targetTable.setItem(index, 4, PAM)
989
- self.targetTable.setItem(index, 5, score)
990
- self.targetTable.setItem(index, 6, QtWidgets.QTableWidgetItem("--.--")) # Give "blank" value for Off-Target
991
- self.targetTable.removeCellWidget(index, num_cols-1) # Leave the "Details" column empty
992
- if (item[1] in self.seq_and_avg_list[self.comboBoxGene.currentIndex()].keys()):
993
- OT = QtWidgets.QTableWidgetItem()
994
- OT.setData(QtCore.Qt.EditRole, self.seq_and_avg_list[self.comboBoxGene.currentIndex()][item[1]])
995
- self.targetTable.setItem(index, 6, OT)
996
- if (item[1] in self.detail_output_list[self.comboBoxGene.currentIndex()].keys()):
997
- details = QtWidgets.QPushButton()
998
- details.setText("Details")
999
- details.clicked.connect(self.show_details)
1000
- self.targetTable.setCellWidget(index, 7, details)
1001
- index += 1
1002
- self.targetTable.resizeColumnsToContents()
1003
- except Exception as e:
1004
- logger.critical("Error in displayGeneData() in results.")
1005
- logger.critical(e)
1006
- logger.critical(traceback.format_exc())
1007
- msgBox = QtWidgets.QMessageBox()
1008
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1009
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1010
- msgBox.setWindowTitle("Fatal Error")
1011
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1012
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1013
- msgBox.exec()
1014
-
1015
-
1016
- exit(-1)
1017
-
1018
- # this function is only entered if the user checks the show only cotargeted sequence checkbox
1019
- def remove_single_endo(self, gene):
1020
- try:
1021
- removalDict = dict()
1022
- # go through and figure out which ones need to be shown
1023
- for i in range(len(self.AllData[gene])):
1024
- for j in range(len(self.AllData[gene][i])):
1025
- endoData = self.AllData[gene][i][j][5].split("|")
1026
- if len(endoData) == 1:
1027
- if i not in removalDict:
1028
- removalDict[i] = list()
1029
-
1030
- removalDict[i].append(j)
1031
-
1032
- # now go through and delete them. But you have to go in reverse
1033
- for item in removalDict:
1034
- # for the reverse of that list. This is to keep the program from crashing
1035
- # easier than building a new list honestly
1036
- for index in reversed(removalDict[item]):
1037
- self.AllData[gene][item].pop(index)
1038
- except Exception as e:
1039
- logger.critical("Error in remove_single_endo() in results.")
1040
- logger.critical(e)
1041
- logger.critical(traceback.format_exc())
1042
- msgBox = QtWidgets.QMessageBox()
1043
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1044
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1045
- msgBox.setWindowTitle("Fatal Error")
1046
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1047
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1048
- msgBox.exec()
1049
-
1050
-
1051
- exit(-1)
1052
-
1053
- # this function goes through and combines table rows that have the same location and PAM dir
1054
- # it edits the dictionary data itself
1055
- # currently it does not take the PAM direction into account
1056
- # parameter genename: the key to which part in the dictionary to look at
1057
- def combine_coTargets(self, genename):
1058
- try:
1059
- cotarget_data = list()
1060
- delete_list = list()
1061
- endoList = list()
1062
- endo_lengths = list()
1063
-
1064
- #get endo data
1065
- self.Endos = {}
1066
- f = open(GlobalSettings.appdir + 'CASPERinfo')
1067
- while True:
1068
- line = f.readline()
1069
- if line.startswith('ENDONUCLEASES'):
1070
- while True:
1071
- line = f.readline()
1072
- if (line[0] == "-"):
1073
- break
1074
- line_tokened = line.split(";")
1075
- endo = line_tokened[0]
1076
- self.Endos[endo] = line_tokened[5]
1077
- break
1078
- f.close()
1079
-
1080
- ### Get the endo list data
1081
- for endo_data in self.AllData[genename]: # Loop through each endonuclease
1082
- ### If there is no data for an endo, just return because co-targeting is useless for that one
1083
- if len(endo_data) == 0:
1084
- return
1085
- if len(endoList) == 0: # If nothing has been added to the endo list yet
1086
- endoList.append(endo_data[0][5]) # Add endo name to list
1087
- endo_lengths.append(len(endo_data[0][2])) # Add endo length to list
1088
- elif len(endo_data[0][2]) > endo_lengths[-1]: # Put the endo with the longest PAM first in the list
1089
- endoList.insert(0,endo_data[0][5])
1090
- endo_lengths.insert(0,endo_data[0][5])
1091
- else:
1092
- endoList.append(endo_data[0][5]) # Add endo name to end of list
1093
- endo_lengths.append(len(endo_data[0][2])) # Add endo length to end of list
1094
- cotarget_endo = "|".join(endoList)
1095
-
1096
- ### Get Co-Targets!
1097
- for i, endo_data in enumerate(self.AllData[genename]): # For each endo in the genename block
1098
- if i == 0: # If first endonuclease checked, just append data to lists
1099
- for target_tuple in endo_data: # For each target
1100
- cotarget_data.append(target_tuple) # Store tuple information in list
1101
- else:
1102
- continue
1103
- for i, endo_data in enumerate(self.AllData[genename]): # For each endo in the genename block
1104
- if i == 0: # If first endonuclease checked, just continue
1105
- continue
1106
- else: # If not first endo, check and see if any sequences are cotargets
1107
- for j,cotarget in enumerate(cotarget_data): # For each potential cotarget
1108
- tmp_list = [x for x in endo_data if cotarget[1] == x[1]] # Check if cotarget is also in this endo's targets
1109
- if len(tmp_list) > 0: # If cotarget was found
1110
- new_tuple = tmp_list[0] # cotarget tuple
1111
- if len(new_tuple[2]) > len(cotarget_data[j][2]): # If PAM is longer for this endo...
1112
- cotarget_data[j] = (new_tuple[0],new_tuple[1],new_tuple[2],new_tuple[3],new_tuple[4],cotarget_endo) # Overwrite existing entry with the one containing longest PAM
1113
- else:
1114
- cotarget_data[j] = (cotarget[0],cotarget[1],cotarget[2],cotarget[3],cotarget[4],cotarget_endo) # Overwrite existing entry to have the right endonuclease
1115
- else: # If not cotarget
1116
- delete_list.append(j)
1117
-
1118
- ### Delete ones from cotarget_data that failed (can't do this in the above loop for some reason)
1119
- final_targets = [x for i,x in enumerate(cotarget_data) if i not in delete_list]
1120
- self.AllData[genename].append(final_targets)
1121
-
1122
- except Exception as e:
1123
- logger.critical("Error in combine_coTargets() in results.")
1124
- logger.critical(e)
1125
- logger.critical(traceback.format_exc())
1126
- msgBox = QtWidgets.QMessageBox()
1127
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1128
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1129
- msgBox.setWindowTitle("Fatal Error")
1130
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1131
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1132
- msgBox.exec()
1133
-
1134
-
1135
- exit(-1)
1136
-
1137
- def search_gene(self):
1138
- try:
1139
- search_trms = []
1140
- checkBox = self.sender()
1141
- index = self.targetTable.indexAt(checkBox.pos())
1142
- seq = self.targetTable.item(index.row(),2).text()
1143
- self.highlighted[str(seq)] = checkBox.isChecked()
1144
-
1145
- x=1
1146
- except Exception as e:
1147
- logger.critical("Error in search_gene() in results.")
1148
- logger.critical(e)
1149
- logger.critical(traceback.format_exc())
1150
- msgBox = QtWidgets.QMessageBox()
1151
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1152
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1153
- msgBox.setWindowTitle("Fatal Error")
1154
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1155
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1156
- msgBox.exec()
1157
-
1158
-
1159
- exit(-1)
1160
-
1161
- def item_select(self):
1162
- try:
1163
- print(self.targetTable.selectedItems())
1164
- except Exception as e:
1165
- logger.critical("Error in item_select() in results.")
1166
- logger.critical(e)
1167
- logger.critical(traceback.format_exc())
1168
- msgBox = QtWidgets.QMessageBox()
1169
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1170
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1171
- msgBox.setWindowTitle("Fatal Error")
1172
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1173
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1174
- msgBox.exec()
1175
-
1176
-
1177
- exit(-1)
1178
-
1179
- def getColumnIndexByHeaderName(self, table, header_name):
1180
- # This functin takes a QTableWidget object and header (column) name and returns the index in the table.
1181
- header = table.horizontalHeader()
1182
- for column in range(header.count()):
1183
- logical_index = header.logicalIndex(column)
1184
- if header.model().headerData(logical_index, header.orientation()) == header_name:
1185
- return logical_index
1186
- return None
1187
-
1188
- def table_sorting(self, logicalIndex):
1189
- try:
1190
- if logicalIndex == self.getColumnIndexByHeaderName(self.targetTable, "Details"): # Prevent sorting by Details column to prevent crashing
1191
- return
1192
- self.switcher[logicalIndex] *= -1
1193
- if self.switcher[logicalIndex] == -1:
1194
- self.targetTable.sortItems(logicalIndex, QtCore.Qt.DescendingOrder)
1195
- else:
1196
- self.targetTable.sortItems(logicalIndex, QtCore.Qt.AscendingOrder)
1197
- except Exception as e:
1198
- logger.critical("Error in table_sorting() in results.")
1199
- logger.critical(e)
1200
- logger.critical(traceback.format_exc())
1201
- msgBox = QtWidgets.QMessageBox()
1202
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1203
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1204
- msgBox.setWindowTitle("Fatal Error")
1205
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1206
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1207
- msgBox.exec()
1208
-
1209
-
1210
- exit(-1)
1211
-
1212
- def update_score_filter(self):
1213
- try:
1214
- self.filter_options.minScoreLine.setText(str(self.filter_options.scoreSlider.value()))
1215
- except Exception as e:
1216
- logger.critical("Error in update_score_filter() in results.")
1217
- logger.critical(e)
1218
- logger.critical(traceback.format_exc())
1219
- msgBox = QtWidgets.QMessageBox()
1220
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1221
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1222
- msgBox.setWindowTitle("Fatal Error")
1223
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1224
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1225
- msgBox.exec()
1226
-
1227
-
1228
- exit(-1)
1229
-
1230
- #linked to when the user pushes tools->off target analysis
1231
- def Off_Target_Analysis(self):
1232
- try:
1233
- #build temp file for offtarget to read from
1234
- if platform.system() == 'Windows':
1235
- f = open(GlobalSettings.appdir + 'OffTargetFolder' + '\\temp.txt','w+')
1236
- else:
1237
- f = open(GlobalSettings.appdir + 'OffTargetFolder' + '/temp.txt', 'w+')
1238
- self.OTA.clear()
1239
- #get selected rows
1240
- selected_rows = []
1241
- indexes = self.targetTable.selectionModel().selectedRows()
1242
-
1243
- if len(indexes) == 0:
1244
- msgBox = QtWidgets.QMessageBox()
1245
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1246
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1247
- msgBox.setWindowTitle("No Rows Selected")
1248
- msgBox.setText(
1249
- "Please select rows from the table to pass into the off-target analysis!")
1250
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
1251
- msgBox.exec()
1252
-
1253
- return
1254
-
1255
- for index in indexes:
1256
- selected_rows.append(index.row())
1257
-
1258
- for row in sorted(selected_rows):
1259
- self.OTA.append(row)
1260
- loc = self.targetTable.item(row, 0).text()
1261
- seq = self.targetTable.item(row,2).text()
1262
- strand = self.targetTable.item(row,3).text()
1263
- pam = self.targetTable.item(row,4).text()
1264
- score = self.targetTable.item(row,5).text()
1265
- self.rows_and_seq_list[self.comboBoxGene.currentIndex()][seq] = row
1266
- output = str(loc) + ';' + str(seq) + ";" + str(pam) + ";" + score + ";" + str(strand)
1267
- f.write(output + '\n')
1268
- f.close()
1269
- #only make off target object if first time, otherwise just
1270
- #reshow the object
1271
- if self.first_boot:
1272
- self.first_boot = False
1273
- self.off_tar_win = OffTarget.OffTarget()
1274
- self.off_tar_win.submitButton.clicked.connect(self.refresh_data)
1275
- center_ui(self.off_tar_win)
1276
- ref_org = str(GlobalSettings.mainWindow.orgChoice.currentText()) ### Set default reference organism to the organism that is being targeted
1277
- index = self.off_tar_win.OrgcomboBox.findText(ref_org) ### Find organism in combo box list
1278
- self.off_tar_win.OrgcomboBox.setCurrentIndex(index) ### Set combo box to appropriate index
1279
- self.off_tar_win.show()
1280
- self.off_tar_win.activateWindow()
1281
- f.close()
1282
- except Exception as e:
1283
- logger.critical("Error in Off_Target_Analysis() in results.")
1284
- logger.critical(e)
1285
- logger.critical(traceback.format_exc())
1286
- msgBox = QtWidgets.QMessageBox()
1287
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1288
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1289
- msgBox.setWindowTitle("Fatal Error")
1290
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1291
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1292
- msgBox.exec()
1293
-
1294
-
1295
- exit(-1)
1296
-
1297
- #refresh data is linked to the submit button on the off target analysis UI
1298
- def refresh_data(self):
1299
- try:
1300
- #setup filename based on output name given in OffTarget
1301
- filename = self.off_tar_win.output_path
1302
-
1303
- # if the user hits submit without running the program, do nothing
1304
- if not self.off_tar_win.run_clicked:
1305
- msgBox = QtWidgets.QMessageBox()
1306
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1307
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1308
- msgBox.setWindowTitle("File Not Found")
1309
- msgBox.setText(
1310
- "There was an error with the Off Target execution. No results file was found.")
1311
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
1312
- msgBox.exec()
1313
- return
1314
-
1315
- self.off_tar_win.hide()
1316
- filename = filename[:len(filename)-1]
1317
- filename = filename[1:]
1318
- filename = filename.replace(r'\\', '\\')
1319
- filename = filename.replace('"', '')
1320
- self.files_list.append(filename)
1321
- try:
1322
- out_file = open(filename, "r")
1323
- except:
1324
- msgBox = QtWidgets.QMessageBox()
1325
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1326
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1327
- msgBox.setWindowTitle("Unable to Open File")
1328
- msgBox.setText(
1329
- "There was an error with the Off Target execution. The results file was either not found or not able to be opened.")
1330
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
1331
- msgBox.exec()
1332
-
1333
- return
1334
-
1335
- #read the first line : either AVG or DETAILED OUTPUT
1336
- output_type = out_file.readline()
1337
- output_type = output_type.strip('\r\n')
1338
-
1339
- #parse based on whether avg or detailed output
1340
- line_cnt = 0
1341
- headers = get_table_headers(self.targetTable) # Get table headers
1342
- num_cols = len(headers) # Get number of columns
1343
- if(output_type == "AVG OUTPUT"):
1344
- for line in out_file:
1345
- line = line.strip('\n')
1346
- if (line != ''):
1347
- values = line.split(":")
1348
- row = self.rows_and_seq_list[self.comboBoxGene.currentIndex()][values[0]]
1349
- OT = QtWidgets.QTableWidgetItem()
1350
- OT.setData(QtCore.Qt.EditRole, values[1])
1351
- self.targetTable.setItem(row, num_cols-2, OT) # Set the OT score to the second to last column
1352
- self.seq_and_avg_list[self.comboBoxGene.currentIndex()][values[0]] = values[1]
1353
- line_cnt += 1
1354
- else:
1355
- details_bool = False
1356
- temp_list = []
1357
- values = []
1358
- for line in out_file:
1359
- line = line.strip('\n')
1360
- if(line.find(':') != -1):
1361
- if(details_bool == True):
1362
- self.detail_output_list[self.comboBoxGene.currentIndex()][values[0]] = temp_list
1363
- details_bool = False
1364
- temp_list = []
1365
- values = line.split(":")
1366
- self.seq_and_avg_list[self.comboBoxGene.currentIndex()][values[0]] = values[1]
1367
- row = self.rows_and_seq_list[self.comboBoxGene.currentIndex()][values[0]]
1368
- OT = QtWidgets.QTableWidgetItem()
1369
- OT.setData(QtCore.Qt.EditRole, values[1])
1370
- self.targetTable.setItem(row, num_cols - 2, OT)
1371
- line_cnt += 1
1372
- elif line != "":
1373
- details_bool = True
1374
- temp_list.append(line)
1375
- details = QtWidgets.QPushButton()
1376
- details.setText("Details")
1377
- details.clicked.connect(self.show_details)
1378
- self.targetTable.setCellWidget(row, num_cols - 1, details)
1379
- line_cnt += 1
1380
- if(details_bool == True):
1381
- self.detail_output_list[self.comboBoxGene.currentIndex()][values[0]] = temp_list
1382
-
1383
-
1384
- #make sure OT output file had lines
1385
- if line_cnt < 1:
1386
- msgBox = QtWidgets.QMessageBox()
1387
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1388
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1389
- msgBox.setWindowTitle("File Empty")
1390
- msgBox.setText(
1391
- "There was an error with the Off Target execution. No results were found in the results file.")
1392
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
1393
- msgBox.exec()
1394
-
1395
- return
1396
-
1397
- #print(self.detail_output_list)
1398
- self.targetTable.resizeColumnsToContents()
1399
- out_file.close()
1400
- except Exception as e:
1401
- logger.critical("Error in refresh_data() in results.")
1402
- logger.critical(e)
1403
- logger.critical(traceback.format_exc())
1404
- msgBox = QtWidgets.QMessageBox()
1405
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1406
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1407
- msgBox.setWindowTitle("Fatal Error")
1408
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1409
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1410
- msgBox.exec()
1411
-
1412
-
1413
- exit(-1)
1414
-
1415
- def show_details(self):
1416
- try:
1417
- #create msg box popup for the details | used html to make it easier to style with bold
1418
- button = self.sender()
1419
- index = self.targetTable.indexAt(button.pos())
1420
- msg = QtWidgets.QMessageBox()
1421
- msg.setWindowTitle("Details")
1422
- msg.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1423
- msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
1424
- key = str(self.targetTable.item(index.row(),2).text())
1425
- temp_str = ''
1426
- for items in self.detail_output_list[self.comboBoxGene.currentIndex()][key]:
1427
- temp_str += items + "<br>"
1428
-
1429
- chromo_str = "<html><b>Reference gRNA:</b><br>Location, Sequence, Strand, PAM, On Score<br></html>"
1430
- input_str = self.targetTable.item(index.row(),0).text() + ', ' + key + ', ' + \
1431
- self.targetTable.item(index.row(),3).text() + ', ' + self.targetTable.item(index.row(),4).text() + \
1432
- ', ' + self.targetTable.item(index.row(),5).text() + "<br><br>"
1433
- detail_str = "<html><b>Off-Target Hits:</b><br>Off Score, Chromosome, Location, Sequence<br></html>"
1434
- msg.setText(chromo_str + input_str + detail_str + temp_str)
1435
- msg.exec()
1436
-
1437
- except Exception as e:
1438
- logger.critical("Error in show_details() in results.")
1439
- logger.critical(e)
1440
- logger.critical(traceback.format_exc())
1441
- msgBox = QtWidgets.QMessageBox()
1442
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1443
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1444
- msgBox.setWindowTitle("Fatal Error")
1445
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1446
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1447
- msgBox.exec()
1448
-
1449
-
1450
- exit(-1)
1451
-
1452
- #function to clear highlights in gene viewer and un-select any rows highlighted in main table
1453
- def clear_highlighted_guides(self):
1454
- try:
1455
- # Clear guides from gene viewer
1456
- self.change_indices()
1457
-
1458
- # Clear selected rows in table
1459
- self.checkBoxSelectAll.setChecked(False)
1460
- self.targetTable.selectionModel().clearSelection()
1461
- except Exception as e:
1462
- logger.critical("Error in clear_highlighted_guides() in results.")
1463
- logger.critical(e)
1464
- logger.critical(traceback.format_exc())
1465
- msgBox = QtWidgets.QMessageBox()
1466
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1467
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1468
- msgBox.setWindowTitle("Fatal Error")
1469
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1470
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1471
- msgBox.exec()
1472
-
1473
-
1474
- exit(-1)
1475
-
1476
- # this function calls the closingWindow class.
1477
- def closeEvent(self, event):
1478
- try:
1479
- GlobalSettings.mainWindow.closeFunction()
1480
- event.accept()
1481
- except Exception as e:
1482
- logger.critical("Error in closeEvent() in results.")
1483
- logger.critical(e)
1484
- logger.critical(traceback.format_exc())
1485
- msgBox = QtWidgets.QMessageBox()
1486
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1487
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1488
- msgBox.setWindowTitle("Fatal Error")
1489
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1490
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1491
- msgBox.exec()
1492
-
1493
-
1494
- exit(-1)
1495
-
1496
- ############################################
1497
- # All Gene Viewer functions are below!
1498
- ############################################
1499
- # It will go based on the lengths stored in the comboGeneBox dictionary
1500
- def load_gene_viewer(self):
1501
- try:
1502
- if GlobalSettings.mainWindow.annotation_files.currentText() != "None":
1503
- sequence = ""
1504
- # for each gene selected from the results window
1505
- for item in self.featureDict:
1506
- sequence, chrom_len = self.sequence_finder(self.featureDict[item])
1507
- self.featureNTDict[item] = sequence
1508
- self.chromDict[item] = chrom_len
1509
- self.lineEditStart.setEnabled(True)
1510
- self.lineEditEnd.setEnabled(True)
1511
- self.change_start_end_button.setEnabled(True)
1512
- self.displayGeneViewer.setEnabled(True)
1513
- self.displayGeneViewer.setChecked(0)
1514
- self.checkGeneViewer()
1515
- else:
1516
- self.displayGeneViewer.setEnabled(False) # Disable Gene Viewer if no annotation file has been selected
1517
- return
1518
- except Exception as e:
1519
- logger.critical("Error in load_gene_viewer() in results.")
1520
- logger.critical(e)
1521
- logger.critical(traceback.format_exc())
1522
- msgBox = QtWidgets.QMessageBox()
1523
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1524
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1525
- msgBox.setWindowTitle("Fatal Error")
1526
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1527
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1528
- msgBox.exec()
1529
-
1530
-
1531
- exit(-1)
1532
-
1533
- # This function takes the location data for a feature- or position-based search
1534
- # and returns the appropriate NT sequence from a GenBank formatted annotation file using BioPython's SeqIO.parse() method
1535
- def sequence_finder(self, location_data):
1536
- try:
1537
- ### Start up the function
1538
- chrom_index = location_data[0]-1 # This is the chromosome we need to pull sequence data from. (Python indexing, so chromosome 1 is index 0)
1539
- start = location_data[1]
1540
- end = location_data[2]
1541
- ### Pull the sequence information from the GenBank file if present
1542
- if self.annotation_path != "":
1543
- parser = SeqIO.parse(self.annotation_path,'genbank') # Initialize parser object for GenBank file
1544
- for i,record in enumerate(parser): # Loop through chromosomes
1545
- if chrom_index == i: # If this is the correct chromosome
1546
- chrom_seq = str(record.seq).strip()
1547
- ### Get appropriate sequence and padding (for visualizing gRNAs that appear at extreme ends of region)
1548
- if (start - 30) >= 0: # Check to make sure there is enough 5' end of gene to pull the padding from, so indexing error isn't raised
1549
- five_prime_tail = chrom_seq[(start-30):start]
1550
- else:
1551
- five_prime_tail = ""
1552
- if len(chrom_seq) >= (end + 30): # Check to make sure there is enough 3' end of gene to pull the padding from, so indexing error isn't raised
1553
- three_prime_tail = chrom_seq[end:end+30]
1554
- else:
1555
- three_prime_tail = ""
1556
- my_seq = chrom_seq[start:end] # Get the sequence from the specified location
1557
- ret_sequence = five_prime_tail.lower() + my_seq.upper() + three_prime_tail.lower() # Add padding to the sequence
1558
- return ret_sequence, len(chrom_seq)
1559
- else: # If this is not the right chromosome, go to the next one
1560
- continue
1561
- else:
1562
- return
1563
-
1564
- except Exception as e:
1565
- logger.critical("Error in sequence_finder() in results.")
1566
- logger.critical(e)
1567
- logger.critical(traceback.format_exc())
1568
- msgBox = QtWidgets.QMessageBox()
1569
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1570
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1571
- msgBox.setWindowTitle("Fatal Error")
1572
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1573
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1574
- msgBox.exec()
1575
-
1576
-
1577
- exit(-1)
1578
-
1579
- #show filters UI
1580
- def show_filter_options(self):
1581
- try:
1582
- self.filter_options.centerUI()
1583
- self.filter_options.show()
1584
- self.filter_options.activateWindow()
1585
- except Exception as e:
1586
- logger.critical("Error in show_filter_options() in results.")
1587
- logger.critical(e)
1588
- logger.critical(traceback.format_exc())
1589
- msgBox = QtWidgets.QMessageBox()
1590
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1591
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1592
- msgBox.setWindowTitle("Fatal Error")
1593
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1594
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1595
- msgBox.exec()
1596
- exit(-1)
1597
-
1598
- #show scoring window UI
1599
- def show_scoring_window(self):
1600
- try:
1601
- # Check to make sure gRNAs were highlighted
1602
- selectedList = self.targetTable.selectedItems()
1603
- if len(selectedList) <= 0:
1604
- msgBox = QtWidgets.QMessageBox()
1605
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1606
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1607
- msgBox.setWindowTitle("Nothing Selected")
1608
- msgBox.setText("No guides were highlighted. Please highlight the guides you want to score!")
1609
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
1610
- msgBox.exec()
1611
- return
1612
- else:
1613
- self.scoring_window.scaleUI()
1614
- self.scoring_window.centerUI()
1615
- self.scoring_window.show()
1616
- self.scoring_window.activateWindow()
1617
-
1618
- except Exception as e:
1619
- logger.critical("Error in show_scoring_window() in results.")
1620
- logger.critical(e)
1621
- logger.critical(traceback.format_exc())
1622
- msgBox = QtWidgets.QMessageBox()
1623
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1624
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1625
- msgBox.setWindowTitle("Fatal Error")
1626
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1627
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1628
- msgBox.exec()
1629
- exit(-1)
1630
-
1631
- except Exception as e:
1632
- logger.critical("Error in show_scoring_window() in results.")
1633
- logger.critical(e)
1634
- logger.critical(traceback.format_exc())
1635
- msgBox = QtWidgets.QMessageBox()
1636
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1637
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1638
- msgBox.setWindowTitle("Fatal Error")
1639
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1640
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1641
- msgBox.exec()
1642
- exit(-1)
1643
-
1644
- class Filter_Options(QtWidgets.QMainWindow):
1645
- def __init__(self, parent=None):
1646
- try:
1647
- super(Filter_Options, self).__init__(parent)
1648
- uic.loadUi(GlobalSettings.appdir + 'ui/filter_options.ui', self)
1649
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
1650
- self.setWindowTitle("Filter Options")
1651
- self.minScoreLine.setText("0")
1652
- groupbox_style = """
1653
- QGroupBox:title{subcontrol-origin: margin;
1654
- left: 10px;
1655
- padding: 0 5px 0 5px;}
1656
- QGroupBox#filterBox{border: 2px solid rgb(111,181,110);
1657
- border-radius: 9px;
1658
- margin-top: 10px;}"""
1659
- self.filterBox.setStyleSheet(groupbox_style)
1660
-
1661
- #scale UI
1662
- self.scaleUI()
1663
-
1664
- except Exception as e:
1665
- logger.critical("Error initializing Filter_Options class in results.")
1666
- logger.critical(e)
1667
- logger.critical(traceback.format_exc())
1668
- msgBox = QtWidgets.QMessageBox()
1669
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1670
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1671
- msgBox.setWindowTitle("Fatal Error")
1672
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1673
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1674
- msgBox.exec()
1675
- exit(-1)
1676
-
1677
- # scale UI based on current screen
1678
- def scaleUI(self):
1679
- try:
1680
- self.repaint()
1681
- QtWidgets.QApplication.processEvents()
1682
-
1683
- screen = self.screen()
1684
- dpi = screen.physicalDotsPerInch()
1685
- width = screen.geometry().width()
1686
- height = screen.geometry().height()
1687
-
1688
- # font scaling
1689
- # 16px is used for 92 dpi / 1920x1080
1690
- fontSize = 12
1691
- self.fontSize = fontSize
1692
- self.centralWidget().setStyleSheet("font: " + str(fontSize) + "pt 'Arial';")
1693
-
1694
- # CASPER header scaling
1695
- fontSize = 20
1696
- self.title.setStyleSheet("font: bold " + str(fontSize) + "pt 'Arial';")
1697
-
1698
- self.adjustSize()
1699
-
1700
- currentWidth = self.size().width()
1701
- currentHeight = self.size().height()
1702
-
1703
- # window scaling
1704
- # 1920x1080 => 850x750
1705
- scaledWidth = int((width * 350) / 1920)
1706
- scaledHeight = int((height * 250) / 1080)
1707
-
1708
- if scaledHeight < currentHeight:
1709
- scaledHeight = currentHeight
1710
- if scaledWidth < currentWidth:
1711
- scaledWidth = currentWidth
1712
-
1713
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
1714
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
1715
- x = centerPoint.x()
1716
- y = centerPoint.y()
1717
- x = x - (math.ceil(scaledWidth / 2))
1718
- y = y - (math.ceil(scaledHeight / 2))
1719
- self.setGeometry(x, y, scaledWidth, scaledHeight)
1720
-
1721
- self.repaint()
1722
- QtWidgets.QApplication.processEvents()
1723
- except Exception as e:
1724
- logger.critical("Error in scaleUI() in filter options in results.")
1725
- logger.critical(e)
1726
- logger.critical(traceback.format_exc())
1727
- msgBox = QtWidgets.QMessageBox()
1728
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1729
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1730
- msgBox.setWindowTitle("Fatal Error")
1731
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1732
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1733
- msgBox.exec()
1734
- exit(-1)
1735
-
1736
- # center UI on current screen
1737
- def centerUI(self):
1738
- try:
1739
- self.repaint()
1740
- QtWidgets.QApplication.processEvents()
1741
-
1742
- # center window on current screen
1743
- width = self.width()
1744
- height = self.height()
1745
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
1746
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
1747
- x = centerPoint.x()
1748
- y = centerPoint.y()
1749
- x = x - (math.ceil(width / 2))
1750
- y = y - (math.ceil(height / 2))
1751
- self.setGeometry(x, y, width, height)
1752
- self.repaint()
1753
- QtWidgets.QApplication.processEvents()
1754
- except Exception as e:
1755
- logger.critical("Error in centerUI() in filter options in results.")
1756
- logger.critical(e)
1757
- logger.critical(traceback.format_exc())
1758
- msgBox = QtWidgets.QMessageBox()
1759
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
1760
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
1761
- msgBox.setWindowTitle("Fatal Error")
1762
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
1763
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
1764
- msgBox.exec()
1765
- exit(-1)
1766
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
controllers/multitargeting.py DELETED
@@ -1,825 +0,0 @@
1
- from PyQt5 import QtWidgets, Qt, QtGui, QtCore, uic
2
- from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
3
- from matplotlib.figure import Figure
4
- import models.GlobalSettings as GlobalSettings
5
- import matplotlib
6
- from utils.Algorithms import SeqTranslate
7
- from models.CSPRparser import CSPRparser
8
- from matplotlib.ticker import MaxNLocator
9
- import os
10
- import sqlite3
11
- import gzip
12
- from collections import Counter
13
- import statistics
14
- import traceback
15
- import math
16
- import numpy as np
17
- from matplotlib.widgets import Slider
18
- from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
19
- from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
20
- import matplotlib.pyplot as plt
21
- from utils.ui import show_message, show_error, scale_ui, center_ui
22
-
23
- logger = GlobalSettings.logger
24
-
25
- class Multitargeting(QtWidgets.QMainWindow):
26
- def __init__(self):
27
- try:
28
- self.count = 0
29
- super(Multitargeting, self).__init__()
30
- uic.loadUi(GlobalSettings.appdir + 'ui/mt.ui', self)
31
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
32
- self.multitargeting_statistics = Multitargeting_Statistics()
33
-
34
- self.sq = SeqTranslate() # SeqTranslate object used in class
35
- self.line_bool = False # Used to check if VBoxLayout already has canvas in it
36
- self.bar_bool = False # Used to check if VBoxLayout already has canvas in it
37
- self.seed_bar_bool = False # Used to check if VBoxLayout already has canvas in it
38
-
39
- # GroupBox Styling
40
- groupbox_style = """
41
- QGroupBox:title{subcontrol-origin: margin;
42
- left: 10px;
43
- padding: 0 5px 0 15px;}
44
- QGroupBox#groupBox{border: 2px solid rgb(111,181,110);
45
- border-radius: 9px;
46
- font: bold;
47
- margin-top: 10px;}"""
48
- self.groupBox.setStyleSheet(groupbox_style)
49
- self.groupBox_2.setStyleSheet(groupbox_style.replace("groupBox","groupBox_2"))
50
- self.groupBox_3.setStyleSheet(groupbox_style.replace("groupBox","groupBox_3"))
51
-
52
- #layout for table
53
- self.table.setColumnCount(8)
54
- self.table.setShowGrid(False)
55
- # for keeping track of where we are in the sorting clicking for each column
56
- self.switcher_table = [1, 1, 1, 1, 1, 1, 1, 1]
57
- self.table.setHorizontalHeaderLabels(
58
- ["Seed", "Total Repeats", "Avg. Repeats/Scaffold", "Consensus Sequence", "% Consensus",
59
- "Score", "PAM", "Strand"])
60
- self.table.horizontalHeader().setSectionsClickable(True)
61
- self.table.horizontalHeader().sectionClicked.connect(self.table_sorting)
62
- self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
63
- self.table.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
64
- self.table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
65
- self.table.resizeColumnsToContents()
66
-
67
- # Initializes layouts for the graphs
68
- self.global_line = QtWidgets.QVBoxLayout()
69
- self.global_bar = QtWidgets.QVBoxLayout()
70
- self.seed_bar = QtWidgets.QVBoxLayout()
71
- self.global_line.setContentsMargins(0,0,0,0)
72
- self.global_bar.setContentsMargins(0,0,0,0)
73
- self.seed_bar.setContentsMargins(0,0,0,0)
74
- self.chrom_viewer_layout = QtWidgets.QVBoxLayout()
75
- self.chrom_viewer_layout.setContentsMargins(0,0,0,0)
76
-
77
- self.data = ""
78
- self.shortHand = ""
79
- self.chromo_length = list()
80
-
81
- # Listeners for changing the seed sequence or the .cspr file
82
- self.Analyze_Button.clicked.connect(self.make_graphs)
83
- self.statistics_overview.clicked.connect(self.show_statistics)
84
- self.export_button.clicked.connect(self.export_tool)
85
- self.selectAll.stateChanged.connect(self.select_all)
86
- self.selectAll.setEnabled(False)
87
-
88
- # go back to main window
89
- self.back_button.clicked.connect(self.go_back)
90
-
91
- # Statistics storage variables
92
- self.max_repeats = 1
93
- self.average = 0
94
- self.median = 0
95
- self.mode = 0
96
- self.average_unique = 0
97
- self.average_rep = 0
98
- self.bar_coords = []
99
- self.seed_id_seq_pair = {}
100
-
101
- self.parser = CSPRparser("")
102
-
103
- self.ready_chromo_min_max = True
104
- self.ready_chromo_make_graph = True
105
- self.info_path = os.getcwd()
106
-
107
- self.scene = QtWidgets.QGraphicsScene()
108
- self.scene2 = QtWidgets.QGraphicsScene()
109
- self.graphicsView_2.setScene(self.scene2)
110
- self.scrollArea.viewport().installEventFilter(self)
111
- self.graphicsView_2.viewport().installEventFilter(self)
112
-
113
- self.loading_window = loading_window()
114
-
115
- #sql query settings
116
- self.row_limit = 1000
117
- self.sql_query_settings.clicked.connect(self.update_sql_query_settings)
118
- self.sql_settings = sql_query_settings()
119
- self.sql_settings.row_count.textChanged.connect(self.sql_row_count_value_changed)
120
-
121
- self.first_show = True
122
- scale_ui(self, custom_scale_width=1400, custom_scale_height=900)
123
-
124
- dpi = self.screen().physicalDotsPerInch()
125
- self.dpi = dpi
126
-
127
- except Exception as e:
128
- show_error("Error initializing Multi-targeting.", e)
129
-
130
- def select_all(self):
131
- try:
132
- if self.selectAll.isChecked():
133
- self.table.selectAll()
134
- else:
135
- self.table.clearSelection()
136
- except Exception as e:
137
- show_error("Error in selectAll() in multitargeting.", e)
138
-
139
- def export_tool(self):
140
- try:
141
- select_items = self.table.selectedItems()
142
- if len(select_items) <= 0:
143
- show_message(
144
- fontSize=12,
145
- icon=QtWidgets.QMessageBox.Icon.Critical,
146
- title="No targets were highlighted",
147
- message="Please highlight the targets you want to be exported to a CSV File!"
148
- )
149
- return
150
- GlobalSettings.mainWindow.export_tool_window.launch(select_items,"mt")
151
- except Exception as e:
152
- show_error("Error in export_tool() in multi-targeting.", e)
153
-
154
- def show_statistics(self):
155
- try:
156
- if (self.line_bool and self.bar_bool):
157
- center_ui(self.multitargeting_statistics)
158
- self.multitargeting_statistics.show()
159
- self.multitargeting_statistics.activateWindow()
160
- else:
161
- show_message(
162
- fontSize=12,
163
- icon=QtWidgets.QMessageBox.Icon.Critical,
164
- title="No analysis run.",
165
- message="Multitargeting Analysis must be performed before viewing statistics.\n\nSelect an organism and endonuclease and click 'Analyze' then try again."
166
- )
167
- return True
168
- except Exception as e:
169
- show_error("Error in show_statistics() in multi-targeting.", e)
170
-
171
- #event handler to show details of targets in chromosome viewer while hovering over canvases
172
- def chromosome_event_handler(self, event):
173
- try:
174
- #get current moust location
175
- x = event.xdata
176
- y = event.y
177
-
178
- #get event data relative to the canvas (chromosome) the viewer is hovering at
179
- curr_chromosome = self.canvas_chromosome_map[event.canvas]
180
- chromosome_seed_data = self.event_data[curr_chromosome]
181
-
182
- #get targets within small range of the mouse location
183
- local_targets = []
184
- for entry in chromosome_seed_data:
185
- try:
186
- if x >= entry[0] - 0.001 and x <= entry[0] + 0.001:
187
- local_targets.append(entry)
188
- except:
189
- pass
190
-
191
- #make sure targets are found before overwriting the viewers details
192
- if local_targets != []:
193
- #prep the viewer to show the target details
194
- self.scene2 = QtWidgets.QGraphicsScene()
195
- self.graphicsView_2.setScene(self.scene2)
196
- output = str()
197
- for target in local_targets:
198
- output += f"Location: {target[1]} | Seq: {target[2]} | PAM: {target[3]} | SCR: {target[4]} | DIRA: {target[5]}\n"
199
-
200
- text = self.scene2.addText(output)
201
- font = QtGui.QFont()
202
- font.setPointSize(self.fontSize-2)
203
- text.setFont(font)
204
-
205
- except Exception as e:
206
- show_error("Error in event_data() in multi-targeting.", e)
207
-
208
- def launch(self):
209
- try:
210
- self.get_data()
211
- except Exception as e:
212
- show_error("Error in launch() in multi-targeting.", e)
213
-
214
- #button trigger for sql settings
215
- def update_sql_query_settings(self):
216
- try:
217
- center_ui(self.sql_settings)
218
- self.sql_settings.show()
219
- self.sql_settings.activateWindow()
220
- except Exception as e:
221
- show_error("Error in update_sql_query_settings() in multi-targeting.", e)
222
-
223
- #trigger for if sql line edit value has changed
224
- def sql_row_count_value_changed(self):
225
- try:
226
- self.row_limit = int(self.sql_settings.row_count.text())
227
- except Exception as e:
228
- show_error("Error in sql_row_count_value_changed() in multi-targeting.", e)
229
- pass
230
-
231
- def get_data(self):
232
- try:
233
- #disconnect index changed signal on endo dropdown if there is one
234
- try:
235
- self.organism_drop.currentIndexChanged.disconnect()
236
- except:
237
- pass
238
- try:
239
- self.endo_drop.currentIndexChanged.disconnect()
240
- except:
241
- pass
242
-
243
-
244
- self.organism_drop.clear()
245
- self.endo_drop.clear()
246
-
247
- onlyfiles = [f for f in os.listdir(GlobalSettings.CSPR_DB) if os.path.isfile(os.path.join(GlobalSettings.CSPR_DB, f))]
248
- self.organisms_to_files = {}
249
- self.organisms_to_endos = {}
250
- # shortName = {}
251
- self.endo_drop.clear()
252
- for file in onlyfiles:
253
- if file.find('.cspr') != -1:
254
- newname = file[0:-4]
255
- endo = newname[newname.rfind("_") + 1:-1]
256
- hold = open(file, 'r')
257
- buf = (hold.readline())
258
- hold.close()
259
- buf = str(buf)
260
- buf = buf.strip()
261
- species = buf.replace("GENOME: ", "")
262
-
263
- if species in self.organisms_to_files:
264
- self.organisms_to_files[species][endo] = [file, file.replace(".cspr", "_repeats.db")]
265
- else:
266
- self.organisms_to_files[species] = {}
267
- self.organisms_to_files[species][endo] = [file, file.replace(".cspr", "_repeats.db")]
268
-
269
- if species in self.organisms_to_endos:
270
- self.organisms_to_endos[species].append(endo)
271
- else:
272
- self.organisms_to_endos[species] = [endo]
273
- if self.organism_drop.findText(species) == -1:
274
- self.organism_drop.addItem(species)
275
-
276
- #fill in endos dropdown based on current organism
277
- endos = self.organisms_to_endos[str(self.organism_drop.currentText())]
278
- self.endo_drop.addItems(endos)
279
- self.organism_drop.currentIndexChanged.connect(self.update_endos)
280
-
281
- #update file names for current org/endo combo
282
- self.cspr_file = self.organisms_to_files[str(self.organism_drop.currentText())][endos[0]][0]
283
- self.db_file = self.organisms_to_files[str(self.organism_drop.currentText())][endos[0]][1]
284
- except Exception as e:
285
- show_error("Error in get_data() in multi-targeting.", e)
286
-
287
- def update_endos(self):
288
- try:
289
- #try to disconnect index changed signal on endo dropdown if there is one
290
- try:
291
- self.endo_drop.currentIndexChanged.disconnect()
292
- except:
293
- pass
294
-
295
- #clear endo dropdown and fill in with endos relative to the current organism
296
- self.endo_drop.clear()
297
- endos = self.organisms_to_endos[str(self.organism_drop.currentText())]
298
- self.endo_drop.addItems(endos)
299
- except Exception as e:
300
- show_error("Error in update_endos() in multi-targeting.", e)
301
-
302
- def make_graphs(self):
303
- try:
304
- self.cspr_file = self.organisms_to_files[str(self.organism_drop.currentText())][str(self.endo_drop.currentText())][0]
305
- self.db_file = self.organisms_to_files[str(self.organism_drop.currentText())][str(self.endo_drop.currentText())][1]
306
-
307
- self.loading_window.loading_bar.setValue(0)
308
- center_ui(self.loading_window)
309
- self.loading_window.show()
310
- QtCore.QCoreApplication.processEvents()
311
- self.chromo_length.clear()
312
- self.loading_window.loading_bar.setValue(10)
313
- self.plot_repeats_vs_seeds()
314
- self.loading_window.loading_bar.setValue(30)
315
- self.bar_seeds_vs_repeats()
316
- self.loading_window.loading_bar.setValue(50)
317
- self.fill_table()
318
- self.table.selectRow(0) # Set the index to first row by default so
319
- # all graphs are generated
320
- self.selectAll.setEnabled(True) # Enable select all checkbox only
321
- # after analysis has been performed
322
- self.loading_window.loading_bar.setValue(100)
323
- self.multitargeting_statistics.avg_rep.setText(str(round(float(self.average),1)))
324
- self.multitargeting_statistics.med_rep.setText(str(round(float(self.median),1)))
325
- self.multitargeting_statistics.mode_rep.setText(str(round(float(self.mode),1)))
326
- self.multitargeting_statistics.nbr_seq.setText(str(round(float(self.repeat_count),1)))
327
- self.loading_window.hide()
328
- self.repaint()
329
- QtWidgets.QApplication.processEvents()
330
-
331
- except Exception as e:
332
- show_error("Error in make_graphs() in multi-targeting.", e)
333
-
334
- #function to fill table in UI
335
- def fill_table(self):
336
- try:
337
- #disable row triggers
338
- try:
339
- self.table.itemSelectionChanged.disconnect()
340
- except:
341
- pass
342
-
343
- #empty table
344
- self.table.setRowCount(0)
345
-
346
- #query db file for data
347
- conn = sqlite3.connect(self.db_file)
348
- c = conn.cursor()
349
- row_cnt = 0
350
-
351
- if self.row_limit == -1:
352
- sql_query = "SELECT * FROM repeats ORDER BY count DESC;"
353
- else:
354
- sql_query = "SELECT * FROM repeats ORDER BY count DESC LIMIT 0, " + str(self.row_limit) + ";"
355
-
356
- for repeat in c.execute(sql_query):
357
- #expand table by 1 row
358
- self.table.setRowCount(row_cnt + 1)
359
-
360
- #extract repeat info
361
- seed = repeat[0]
362
- chroms = repeat[1].split(",")
363
- locs = repeat[2].split(",")
364
- threes = repeat[3].split(",")
365
- fives = repeat[4].split(",")
366
- pams = repeat[5].split(",")
367
- scores = repeat[6].split(",")
368
- count = repeat[7]
369
-
370
- #push seed
371
- table_seed = QtWidgets.QTableWidgetItem()
372
- table_seed.setData(QtCore.Qt.EditRole, seed)
373
- table_seed.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
374
- self.table.setItem(row_cnt, 0, table_seed)
375
-
376
- if len(threes) < len(fives):
377
- for i in range(len(fives) - len(threes)):
378
- threes.append('')
379
-
380
- elif len(fives) < len(threes):
381
- for i in range(len(threes) - len(fives)):
382
- fives.append('')
383
-
384
- majority_index = 0
385
- three_prime, five_prime, both_prime = False, False, False
386
- if threes[0] == '':
387
- majority = max(set(fives), key=fives.count)
388
- majority_index = fives.index(majority)
389
- five_prime = True
390
- elif fives[0] == '':
391
- majority = max(set(threes), key=threes.count)
392
- majority_index = threes.index(majority)
393
- three_prime = True
394
- else:
395
- # account for both 3 and 5 present
396
- threes_and_fives = []
397
- for i in range(len(threes)):
398
- threes_and_fives.append(threes[i] + fives[i])
399
- majority = max(set(threes_and_fives), key=threes_and_fives.count)
400
- majority_index = threes_and_fives.index(majority)
401
- both_prime = True
402
-
403
- # push total count
404
- table_count = QtWidgets.QTableWidgetItem()
405
- table_count.setData(QtCore.Qt.EditRole, count)
406
- table_count.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
407
- self.table.setItem(row_cnt, 1, table_count)
408
-
409
- # push avg repeat
410
- location_repeat_counts = Counter(chroms)
411
- avg_rep_per_scaff = sum(location_repeat_counts.values()) / len(location_repeat_counts.values())
412
- avg_rep = QtWidgets.QTableWidgetItem()
413
- avg_rep_per_scaff = float("%.2f" % avg_rep_per_scaff)
414
- avg_rep.setData(QtCore.Qt.EditRole, avg_rep_per_scaff)
415
- avg_rep.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
416
- self.table.setItem(row_cnt, 2, avg_rep)
417
-
418
- # push seq
419
- seq = QtWidgets.QTableWidgetItem()
420
- seq.setData(QtCore.Qt.EditRole, fives[majority_index] + seed + threes[majority_index])
421
- seq.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
422
- self.table.setItem(row_cnt, 3, seq)
423
-
424
- # push percent consensus
425
- perc_cons = QtWidgets.QTableWidgetItem()
426
- percent_consensus = 0
427
- if five_prime == True:
428
- percent_consensus = (fives.count(fives[majority_index]) / len(fives)) * 100
429
- elif three_prime == True:
430
- percent_consensus = (threes.count(threes[majority_index]) / len(threes)) * 100
431
- elif both_prime:
432
- percent_consensus = (threes_and_fives.count(threes_and_fives[majority_index]) / len(threes_and_fives)) * 100
433
-
434
- percent_consensus = float("%.2f" % percent_consensus)
435
- perc_cons.setData(QtCore.Qt.EditRole, percent_consensus)
436
- perc_cons.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
437
- self.table.setItem(row_cnt, 4, perc_cons)
438
-
439
- # push score
440
- score = QtWidgets.QTableWidgetItem()
441
- score.setData(QtCore.Qt.EditRole, scores[majority_index])
442
- score.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
443
- self.table.setItem(row_cnt, 5, score)
444
-
445
- # push PAM
446
- pam = QtWidgets.QTableWidgetItem()
447
- pam.setData(QtCore.Qt.EditRole, pams[majority_index])
448
- pam.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
449
- self.table.setItem(row_cnt, 6, pam)
450
-
451
- # push strand
452
- strand_val = ""
453
- if int(locs[majority_index]) < 0:
454
- strand_val = "-"
455
- else:
456
- strand_val = "+"
457
-
458
- strand = QtWidgets.QTableWidgetItem()
459
- strand.setData(QtCore.Qt.EditRole, strand_val)
460
- strand.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
461
- self.table.setItem(row_cnt, 7, strand)
462
-
463
- #increment row count
464
- row_cnt += 1
465
-
466
- #close db connection
467
- c.close()
468
- conn.close()
469
-
470
- #resize columns in table to match contents
471
- self.table.resizeColumnsToContents()
472
-
473
- #reconnect row trigger
474
- self.table.itemSelectionChanged.connect(self.row_selection_trigger)
475
- except Exception as e:
476
- show_error("Error in fill_table() in multi-targeting.", e)
477
-
478
- #function for triggering graph updates when user selects row in table
479
- def row_selection_trigger(self):
480
- try:
481
- item = self.table.currentItem()
482
- if item.isSelected() == True:
483
- row_num = item.row()
484
- seed = self.table.item(row_num,0).text()
485
- self.fill_Chromo_Text(seed)
486
- self.chro_bar_create(seed)
487
- except Exception as e:
488
- show_error("Error in row_selection_trigger() in multi-targeting.", e)
489
-
490
- # sorting to table
491
- def table_sorting(self, logicalIndex):
492
- try:
493
- self.switcher_table[logicalIndex] *= -1
494
- if self.switcher_table[logicalIndex] == -1:
495
- self.table.sortItems(logicalIndex, QtCore.Qt.DescendingOrder)
496
- else:
497
- self.table.sortItems(logicalIndex, QtCore.Qt.AscendingOrder)
498
- except Exception as e:
499
- show_error("Error in table_sorting() in multi-targeting.", e)
500
-
501
- #fill in chromo bar visualization
502
- def fill_Chromo_Text(self, seed):
503
- try:
504
- #global dictionary to map canvases to chromosomes
505
- self.canvas_chromosome_map = {}
506
-
507
- # get kstats
508
- kstats = []
509
- with open(self.cspr_file, "r") as f:
510
- for line in f:
511
- buf = str(line)
512
- if buf.find("KARYSTATS") != -1:
513
- buf = buf.replace("KARYSTATS: ", "")
514
- kstats = buf.split(',')
515
- kstats = kstats[:-1]
516
- break
517
-
518
- #get chromosomes/locations of repeats for current seed
519
- conn = sqlite3.connect(self.db_file)
520
- c = conn.cursor()
521
- data = c.execute("SELECT chromosome, location, pam, score, five, three FROM repeats WHERE seed = ? ", (seed,)).fetchone()
522
- c.close()
523
-
524
- #make sure there is data on current seed
525
- if data != None:
526
-
527
- # build out dictionary (seed_data) mapping chromosome numbers to list of repeat locations
528
- # normalize the location values based on kstat value of chromosome
529
- seed_data = {}
530
- self.event_data = {}
531
- data = list(data)
532
- chromo = data[0].split(',')
533
- pos = data[1].split(',')
534
- pam = data[2].split(',')
535
- score = data[3].split(',')
536
- five = data[4].split(',')
537
- three = data[5].split(',')
538
- #get x-cordinates for graphs and event data
539
- for i in range(len(chromo)):
540
- curr_chromo = int(chromo[i])
541
- if int(pos[i]) >= 0:
542
- dir = "+"
543
- else:
544
- dir = "-"
545
- normalized_location = abs(float(pos[i]) / float(kstats[curr_chromo - 1]))
546
- if int(chromo[i]) in seed_data.keys():
547
- seed_data[int(chromo[i])].append(normalized_location)
548
- self.event_data[int(chromo[i])].append([normalized_location, pos[i], five[i] + seed + three[i], pam[i], score[i], dir])
549
- else:
550
- seed_data[int(chromo[i])] = [normalized_location]
551
- self.event_data[int(chromo[i])] = [[normalized_location, pos[i], five[i] + seed + three[i] ,pam[i], score[i], dir]]
552
-
553
- # graph the locations for each chromosome
554
- # Clear out old widgets in layout
555
- for i in reversed(range(self.chrom_viewer_layout.count())):
556
- self.chrom_viewer_layout.itemAt(i).widget().setParent(None)
557
-
558
- top_widget = QtWidgets.QWidget()
559
- top_layout = QtWidgets.QVBoxLayout()
560
-
561
- chromo_keys = sorted(list(seed_data.keys()))
562
-
563
- screen = self.screen()
564
- height = screen.geometry().height()
565
- groupbox_height = int((height * 100) / 1080)
566
-
567
- for i in range(len(chromo_keys)):
568
- curr_chromo = chromo_keys[i]
569
- group_box = QtWidgets.QGroupBox()
570
-
571
- group_box.setTitle(f"Chromosome {curr_chromo}")
572
- group_box.setMinimumHeight(groupbox_height)
573
- group_box.setMaximumHeight(groupbox_height)
574
- layout = QtWidgets.QVBoxLayout(group_box)
575
-
576
- canvas = MplCanvas()
577
- canvas.axes.eventplot(seed_data[curr_chromo])
578
- canvas.mpl_connect("motion_notify_event", self.chromosome_event_handler)
579
-
580
- # surrounding border
581
- canvas.axes.hlines(1.5, -0.01, 1.01, colors="Black", linewidth=1.5)
582
- canvas.axes.hlines(0.5, -0.01, 1.01, colors="Black", linewidth=1.5)
583
- canvas.axes.vlines(-0.01, 0.5, 1.5, colors="Black", linewidth=1.5)
584
- canvas.axes.vlines(1.01, 0.5, 1.5, colors="Black", linewidth=1.5)
585
- canvas.axes.set_ylim(0.45, 1.55)
586
- canvas.axes.set_xlim(-0.05, 1.05)
587
-
588
- canvas.axes.axis('off')
589
- canvas.draw()
590
-
591
- self.canvas_chromosome_map[canvas] = curr_chromo
592
-
593
- layout.addWidget(canvas)
594
- top_layout.addWidget(group_box)
595
-
596
- top_widget.setLayout(top_layout)
597
- self.scrollArea.setWidget(top_widget)
598
-
599
- return True
600
- else:
601
- msgBox = QtWidgets.QMessageBox()
602
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
603
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
604
- msgBox.setWindowTitle("Seed Error")
605
- msgBox.setText("No such seed exists in the repeats section of this organism.")
606
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
607
- msgBox.exec()
608
-
609
- return False
610
- except Exception as e:
611
- show_error("Error in fill_Chromo_text() in multi-targeting.", e)
612
-
613
- # creates bar graph num of repeats vs. chromosome
614
- def chro_bar_create(self, seed):
615
- try:
616
- ###Clear out old widgets in layout
617
- for i in reversed(range(self.seed_bar.count())):
618
- self.seed_bar.itemAt(i).widget().setParent(None)
619
- self.seed_canvas = MplCanvas(self, width=5, height=3, dpi=self.dpi) ###Initialize new Canvas
620
- self.seed_bar.addWidget(self.seed_canvas) ### Add canvas to global line layout
621
- self.repeats_vs_chromo.setLayout(self.seed_bar) ### Add global line layout to repeats vs. seeds line plot widget
622
- y = []
623
- x_labels = []
624
- conn = sqlite3.connect(self.db_file)
625
- c = conn.cursor()
626
- data = c.execute("SELECT chromosome FROM repeats WHERE seed = ? ", (seed,)).fetchone()
627
- c.close()
628
- data = data[0].split(',')
629
- for i in range(len(data)):
630
- data[i] = int(data[i])
631
- bar_data = Counter(data)
632
- for chromo in sorted(bar_data):
633
- x_labels.append(chromo)
634
- y.append(bar_data[chromo])
635
- x = list(range(0, len(x_labels)))
636
-
637
- #the following statements are plottings / formatting for the graph
638
- self.seed_canvas.axes.bar(x, y, align='center')
639
- self.seed_canvas.axes.yaxis.set_major_locator(MaxNLocator(integer=True))
640
- self.seed_canvas.axes.set_ylim(0, max(y) + 1)
641
- self.seed_canvas.axes.set_xticks(x)
642
- self.seed_canvas.axes.set_xticklabels(x_labels)
643
- if len(x_labels) > 10:
644
- tick_spacing = round(len(x_labels)/10)
645
- for i, t in enumerate(self.seed_canvas.axes.get_xticklabels()):
646
- if (i % tick_spacing) != 0:
647
- t.set_visible(False)
648
- self.seed_canvas.axes.set_xlabel('Chromosome', fontsize = 10)
649
- self.seed_canvas.axes.set_ylabel('Number of Repeats', fontsize=10)
650
- self.line_canvas.axes.set_title('Repeats per ID Number',fontsize=10)
651
- self.line_canvas.axes.tick_params(axis='both', which='major', labelsize=8)
652
- self.line_canvas.draw()
653
- except Exception as e:
654
- show_error("Error in chro_bar_create() in multi-targeting.", e)
655
-
656
- def bar_seeds_vs_repeats(self):
657
- try:
658
- ###Clear out old widgets in layout
659
- for i in reversed(range(self.global_bar.count())):
660
- self.global_bar.itemAt(i).widget().setParent(None)
661
- self.bar_canvas = MplCanvas(self, width=5, height=3, dpi=self.dpi) ###Initialize new Canvas
662
- self.global_bar.addWidget(self.bar_canvas) ### Add canvas to global line layout
663
- self.seeds_vs_repeats_bar.setLayout(self.global_bar) ### Add global line layout to repeats vs. seeds line plot widget
664
-
665
- """ Get the data """
666
- conn = sqlite3.connect(self.db_file)
667
- c = conn.cursor()
668
- x_labels = []
669
- y = []
670
- for obj in c.execute("select count, COUNT(count) as cnt from repeats group by count order by cnt DESC;"):
671
- x_labels.append(obj[0])
672
- y.append(obj[1])
673
-
674
- x_labels = sorted(x_labels)
675
-
676
- # the following are plotting / formatting for the graph
677
- self.bar_canvas.axes.scatter(x_labels, y, s=10)
678
- self.bar_canvas.axes.set_xlim(x_labels[0]-0.5, x_labels[-1] + 0.5)
679
- self.bar_canvas.axes.set_yscale('log')
680
- self.bar_canvas.axes.set_xlabel('Number of Repeats', fontsize=10)
681
- self.bar_canvas.axes.set_ylabel('Number of Sequences', fontsize=10)
682
- self.bar_canvas.axes.set_title('Number of Sequences per Number of Repeats',fontsize=10)
683
- self.bar_canvas.axes.tick_params(axis='both', which='major', labelsize=8)
684
- self.bar_canvas.draw()
685
-
686
- self.bar_bool = True
687
- except Exception as e:
688
- show_error("Error in bar_seeds_vs_repeats() in multi-targeting.", e)
689
-
690
- # # plots the repeats per ID number graph as line graph
691
- def plot_repeats_vs_seeds(self):
692
- try:
693
- ###Clear out old widgets in layout
694
- for i in reversed(range(self.global_line.count())):
695
- self.global_line.itemAt(i).widget().setParent(None)
696
- self.line_canvas = MplCanvas(self, width=5, height=3, dpi=self.dpi) ###Initialize new Canvas
697
- self.global_line.addWidget(self.line_canvas) ### Add canvas to global line layout
698
- self.repeats_vs_seeds_line.setLayout(self.global_line) ### Add global line layout to repeats vs. seeds line plot widget
699
-
700
- """ Fetch all the data """
701
- conn = sqlite3.connect(self.db_file)
702
- c = conn.cursor()
703
-
704
- y1 = []
705
- for obj in c.execute("SELECT count from repeats;"):
706
- y1.append(obj[0])
707
-
708
- c.close()
709
-
710
- #get stats
711
- self.average = statistics.mean(y1)
712
- self.mode = statistics.mode(y1)
713
- self.median = statistics.median(y1)
714
- self.repeat_count = len(y1)
715
-
716
- # clear axes
717
- self.line_canvas.axes.clear()
718
- #Plotting / formatting
719
- self.line_canvas.axes.plot(y1)
720
- self.line_canvas.axes.set_xlabel('Seed ID Number',fontsize=10)
721
- self.line_canvas.axes.set_ylabel('Number of Repeats',fontsize=10)
722
- self.line_canvas.axes.set_title('Number of Repeats per Seed ID Number',fontsize=10)
723
- self.line_canvas.axes.tick_params(axis='both', which='major', labelsize=8)
724
- # always redraw at the end
725
- self.line_bool = True
726
- self.line_canvas.draw()
727
- except Exception as e:
728
- show_error("Error in plot_repeats_vs_seeds() in multi-targeting.", e)
729
-
730
- def seed_chromo_changed(self):
731
- try:
732
- self.loading_window.loading_bar.setValue(5)
733
- self.loading_window.show()
734
- QtCore.QCoreApplication.processEvents()
735
- self.seed.setText('')
736
- self.loading_window.loading_bar.setValue(50)
737
- self.loading_window.loading_bar.setValue(100)
738
- self.loading_window.hide()
739
- except Exception as e:
740
- show_error("Error in seed_chromo_changed() in multi-targeting.", e)
741
-
742
- #connects to go back button in bottom left to switch back to the main CASPER window
743
- def go_back(self):
744
- try:
745
- self.sql_settings.hide()
746
- self.multitargeting_statistics.hide()
747
- GlobalSettings.mainWindow.show()
748
- self.hide()
749
- except Exception as e:
750
- show_error("Error in go_back() in multi-targeting.", e)
751
-
752
- # this function calls the closingWindow class.
753
- def closeEvent(self, event):
754
- try:
755
- GlobalSettings.mainWindow.closeFunction()
756
- self.sql_settings.hide()
757
- self.multitargeting_statistics.hide()
758
- event.accept()
759
- except Exception as e:
760
- show_error("Error in closeEvent() in multi-targeting.", e)
761
-
762
- class loading_window(QtWidgets.QMainWindow):
763
- def __init__(self):
764
- try:
765
- super(loading_window, self).__init__()
766
- uic.loadUi(GlobalSettings.appdir + "ui/loading_data_form.ui", self)
767
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
768
- self.loading_bar.setValue(0)
769
- self.setWindowTitle("Loading Data")
770
-
771
- scale_ui(self, custom_scale_width=450, custom_scale_height=125)
772
-
773
- except Exception as e:
774
- show_error("Error initializing loading_window class in multi-targeting.", e)
775
-
776
- class MplCanvas(FigureCanvasQTAgg):
777
- def __init__(self, parent=None, width=5, height=4, dpi=100):
778
- try:
779
- # Create Figure instance
780
- #fig = Figure(figsize=(width, height), dpi=dpi)
781
-
782
- fig = Figure(dpi=dpi, tight_layout=True)
783
- self.axes = fig.add_subplot(111)
784
- self.axes.clear()
785
- super(MplCanvas, self).__init__(fig)
786
-
787
- # Create axes
788
- "this is the one need to be changed and be dynamic for any number of subplots"
789
- #self.axes = fig.add_subplot(111)
790
-
791
- # Display the figure
792
- # FigureCanvasQTAgg.__init__(self, fig)
793
- # self.setParent(parent)
794
- # FigureCanvasQTAgg.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding,
795
- # QtWidgets.QSizePolicy.Expanding)
796
- # FigureCanvasQTAgg.updateGeometry(self)
797
- except Exception as e:
798
- show_error("Error initializing MplCanvas class in multi-targeting.", e)
799
-
800
- class Multitargeting_Statistics(QtWidgets.QMainWindow):
801
- def __init__(self, parent=None):
802
- try:
803
- super(Multitargeting_Statistics, self).__init__(parent)
804
- uic.loadUi(GlobalSettings.appdir + 'ui/multitargeting_stats.ui', self)
805
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
806
- self.setWindowTitle("Statistics")
807
-
808
- scale_ui(self, custom_scale_width=275, custom_scale_height=185)
809
-
810
- except Exception as e:
811
- show_error("Error initializing Multitargeting_Statistics class in multi-targeting.", e)
812
-
813
- class sql_query_settings(QtWidgets.QMainWindow):
814
- def __init__(self):
815
- try:
816
- super(sql_query_settings, self).__init__()
817
- uic.loadUi(GlobalSettings.appdir + "ui/multitargeting_sql_settings.ui", self)
818
- self.setWindowTitle("SQL Settings")
819
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
820
- self.row_count.setValidator(QtGui.QIntValidator())
821
-
822
- scale_ui(self, custom_scale_width=375, custom_scale_height=140)
823
-
824
- except Exception as e:
825
- show_error("Error initializing sql_query_settings class in multi-targeting.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
controllers/ncbi.py DELETED
@@ -1,915 +0,0 @@
1
- from Bio import Entrez
2
- from bs4 import BeautifulSoup
3
- from PyQt5 import QtWidgets, Qt, QtCore, uic
4
- from ftplib import FTP
5
- import gzip
6
- import pandas as pd
7
- import shutil
8
- import os, time
9
- import ssl
10
- import models.GlobalSettings as GlobalSettings
11
- import platform
12
- import traceback
13
- import math
14
- from utils.ui import show_message, show_error, scale_ui, center_ui
15
-
16
- #global logger
17
- logger = GlobalSettings.logger
18
-
19
- ssl._create_default_https_context = ssl._create_unverified_context
20
-
21
- Entrez.email = "casper2informatics@gmail.com"
22
-
23
- #model for filtering columns in ncbi table
24
- class CustomProxyModel(QtCore.QSortFilterProxyModel):
25
- def __init__(self, parent=None):
26
- print("Initializing CustomProxyModel")
27
- try:
28
- super().__init__(parent)
29
- self._filters = dict()
30
- except Exception as e:
31
- show_error("Error initializing CustomProxyModel class in ncbi tool.", e)
32
-
33
- @property
34
- def filters(self):
35
- try:
36
- return self._filters
37
- except Exception as e:
38
- show_error("Error in filter() in custom proxy model in ncbi tool.", e)
39
-
40
- def setFilter(self, expresion, column):
41
- try:
42
- if expresion:
43
- self.filters[column] = expresion
44
- elif column in self.filters:
45
- del self.filters[column]
46
- self.invalidateFilter()
47
- except Exception as e:
48
- show_error("Error in setFilters() in custom proxy model in ncbi tool.", e)
49
-
50
- def filterAcceptsRow(self, source_row, source_parent):
51
- try:
52
- for column, expresion in self.filters.items():
53
- text = self.sourceModel().index(source_row, column, source_parent).data()
54
- regex = QtCore.QRegExp(
55
- expresion, QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp
56
- )
57
- if regex.indexIn(text) == -1:
58
- return False
59
- return True
60
-
61
- except Exception as e:
62
- show_error("Error in filterAcceptsRow() in custom proxy model in ncbi tool.", e)
63
-
64
- #model for the data in the ncbi search table
65
- class PandasModel(QtCore.QAbstractTableModel):
66
- def __init__(self, df=pd.DataFrame(), parent=None):
67
- try:
68
- QtCore.QAbstractTableModel.__init__(self, parent=parent)
69
- self._df = df.copy()
70
- except Exception as e:
71
- show_error("Error initializing PandasModel class in ncbi tool.", e)
72
-
73
- def toDataFrame(self):
74
- try:
75
- return self._df.copy()
76
-
77
- except Exception as e:
78
- show_error("Error in toDataFrame() in Pandas Model in ncbi tool.", e)
79
-
80
- def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
81
- try:
82
- if role != QtCore.Qt.DisplayRole:
83
- return QtCore.QVariant()
84
-
85
- if orientation == QtCore.Qt.Horizontal:
86
- try:
87
- return self._df.columns.tolist()[section]
88
- except (IndexError, ):
89
- return QtCore.QVariant()
90
- elif orientation == QtCore.Qt.Vertical:
91
- try:
92
- return self._df.index.tolist()[section]
93
- except (IndexError, ):
94
- return QtCore.QVariant()
95
- except Exception as e:
96
- show_error("Error in headerData() in Pandas Model in ncbi tool.", e)
97
-
98
- def data(self, index, role=QtCore.Qt.DisplayRole):
99
- try:
100
- if role == QtCore.Qt.TextAlignmentRole:
101
- return QtCore.Qt.AlignCenter
102
- if role != QtCore.Qt.DisplayRole:
103
- return QtCore.QVariant()
104
- if not index.isValid():
105
- return QtCore.QVariant()
106
-
107
- return QtCore.QVariant(str(self._df.iloc[index.row(), index.column()]))
108
-
109
- except Exception as e:
110
- show_error("Error in data() in Pandas Model in ncbi tool.", e)
111
-
112
- def setData(self, index, value, role):
113
- try:
114
- row = self._df.index[index.row()]
115
- col = self._df.columns[index.column()]
116
- if hasattr(value, 'toPyObject'):
117
- # PyQt4 gets a QVariant
118
- value = value.toPyObject()
119
- else:
120
- # PySide gets an unicode
121
- dtype = self._df[col].dtype
122
- if dtype != object:
123
- value = None if value == '' else dtype.type(value)
124
- self._df.set_value(row, col, value)
125
- return True
126
- except Exception as e:
127
- show_error("Error in setData() in Pandas Model in ncbi tool.", e)
128
-
129
- def rowCount(self, parent=QtCore.QModelIndex()):
130
- try:
131
- return len(self._df.index)
132
-
133
- except Exception as e:
134
- show_error("Error in rowCount() in Pandas Model in ncbi tool.", e)
135
-
136
- def columnCount(self, parent=QtCore.QModelIndex()):
137
- try:
138
- return len(self._df.columns)
139
- except Exception as e:
140
- show_error("Error in columnCount() in Pandas Model in ncbi tool.", e)
141
-
142
- def sort(self, column, order):
143
- try:
144
- colname = self._df.columns.tolist()[column]
145
- self.layoutAboutToBeChanged.emit()
146
- self._df.sort_values(colname, ascending=order, inplace=True)
147
- self._df.reset_index(inplace=True, drop=True)
148
- self.layoutChanged.emit()
149
- except Exception as e:
150
- show_error("Error in sort() in Pandas Model in ncbi tool.", e)
151
-
152
- ## Taken from StackOverflow: https://stackoverflow.com/questions/57607072/update-pyqt-progress-from-another-thread-running-ftp-download
153
- class DownloadThread(QtCore.QThread):
154
- """ Overall signals """
155
- finished = QtCore.pyqtSignal(object)
156
- started = QtCore.pyqtSignal(object)
157
-
158
- """ Download specific signals """
159
- data_progress = QtCore.pyqtSignal(object) # This signal emits progress data for the progress bar
160
- data_size = QtCore.pyqtSignal(object) # This signal emits the size of the file being downloaded
161
- file_started = QtCore.pyqtSignal(object) # This signal emits when the file starts downloading
162
- file_finished = QtCore.pyqtSignal(object) # This signal emits the name of the file downloaded
163
-
164
- def __init__(self,parent,url,id):
165
- try:
166
- QtCore.QThread.__init__(self,parent)
167
- self.id = id
168
- self.url = url # Initialize URL
169
- self.ftp = FTP('ftp.ncbi.nlm.nih.gov') # Initialize FTP object
170
- self.ftp.login()
171
- except Exception as e:
172
- show_error("Error initializing Thread class in ncbi tool.", e)
173
-
174
- def run(self):
175
- try:
176
- ### Start by making sure the url is valid
177
- if self.url == "":
178
- self.finished.emit((self.id, False))
179
- return
180
- else:
181
- self.started.emit(self.id)
182
- self.ftp.cwd(self.url) # Change to appropriate directory
183
- dir_files = self.ftp.nlst() # Get list of files in directory
184
- for file in dir_files: # Loop through every file in the directory
185
- if GlobalSettings.mainWindow.ncbi.gbff_checkbox.isChecked(): # If a GBFF is supposed to be downloaded
186
- if file.find('genomic.gbff') != -1: # If a GBFF exists in this directory
187
-
188
- # check OS for output path
189
- if platform.system() == "Windows":
190
- output_file = GlobalSettings.CSPR_DB + "\\GBFF\\" + file
191
- else:
192
- output_file = GlobalSettings.CSPR_DB + "/GBFF/" + file
193
-
194
- self.ftp.voidcmd('TYPE I')
195
- totalsize = self.ftp.size(file) # Get size of file that is being downloaded
196
- # The first signal sets the maximum for the progress bar
197
- self.file_started.emit((self.id,'Downloading GBFF: ' + str(round(totalsize/1e6,2)) + 'MB...',str(totalsize))) # Emit that the file download is starting and size of file
198
- with open(output_file, 'wb') as self.f:
199
- self.ftp.retrbinary(f"RETR {file}", self.file_write) # Download the file, emitting progress as we go
200
- self.decompress_file(output_file) # Decompress the file
201
- self.file_finished.emit((self.id,'GBFF Downloaded!',output_file)) # Once download is finished, emit signal
202
-
203
- if GlobalSettings.mainWindow.ncbi.fna_checkbox.isChecked(): # If a FNA is supposed to be downloaded
204
- if file.find('genomic.fna') != -1 and file.find('_cds_') == -1 and file.find('_rna_') == -1: # If a FNA exists in this directory
205
-
206
- # check OS for output path
207
- if platform.system() == "Windows":
208
- output_file = GlobalSettings.CSPR_DB + "\\FNA\\" + file
209
- else:
210
- output_file = GlobalSettings.CSPR_DB + "/FNA/" + file
211
-
212
- self.ftp.voidcmd('TYPE I')
213
- totalsize = self.ftp.size(file) # Get size of file that is being downloaded
214
- self.file_started.emit((self.id,'Downloading FNA: ' + str(round(totalsize/1e6,2)) + 'MB...',str(totalsize))) # Emit that file download is starting
215
- with open(output_file, 'wb') as self.f:
216
- self.ftp.retrbinary(f"RETR {file}", self.file_write) # Download the file
217
-
218
- self.decompress_file(output_file) # Decompress the file
219
- self.file_finished.emit((self.id,'FNA Downloaded!',output_file)) # Once download is finished, emit signal
220
- self.finished.emit((self.id,True))
221
- self.ftp.quit() # Stop the FTP connection once everything has been downloaded
222
- except Exception as e:
223
- show_error("Error downloading file within DownloadThread class.", e)
224
-
225
- def file_write(self, data):
226
- self.f.write(data) # Write the downloaded data to a file
227
- # The other signals increase a progress
228
- self.data_progress.emit((self.id,str(len(data)))) # Emit a signal updating progress
229
-
230
- def decompress_file(self, filename):
231
- try:
232
- block_size = 65536
233
- with gzip.open(filename, 'rb') as f_in:
234
- with open(str(filename).replace('.gz', ''), 'wb') as f_out:
235
- while True:
236
- block = f_in.read(block_size)
237
- if not block:
238
- break
239
- else:
240
- f_out.write(block)
241
- os.remove(str(filename))
242
- except Exception as e:
243
- show_error("Error in decompress_file() in ncbi tool.", e)
244
-
245
- class NCBI_search_tool(QtWidgets.QMainWindow):
246
- def __init__(self):
247
- try:
248
- print("Initializing NCBI search tool...")
249
- super(NCBI_search_tool, self).__init__()
250
- uic.loadUi(GlobalSettings.appdir + 'ui/ncbi.ui', self)
251
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
252
- self.setWindowTitle("NCBI Download Tool")
253
- self.logicalIndex = 0
254
- self.filters = dict()
255
- self.download_button.clicked.connect(self.download_files_wrapper)
256
- self.search_button.clicked.connect(self.query_db)
257
- self.ncbi_table.verticalHeader().hide()
258
- self.all_rows.clicked.connect(self.select_all)
259
- self.back_button.clicked.connect(self.go_back)
260
- self.ncbi_table.setFocusPolicy(QtCore.Qt.NoFocus)
261
- self.progressBar.setValue(0)
262
- self.rename_window = rename_window()
263
- self.rename_window.submit_button.clicked.connect(self.submit_rename)
264
- self.rename_window.go_back.clicked.connect(self.rename_go_back)
265
- self.df = pd.DataFrame()
266
- groupbox_style = """
267
- QGroupBox:title{subcontrol-origin: margin;
268
- left: 10px;
269
- padding: 0 5px 0 5px;}
270
- QGroupBox#Step1{border: 2px solid rgb(111,181,110);
271
- border-radius: 9px;
272
- font: bold 14pt 'Arial';
273
- margin-top: 10px;}"""
274
- self.Step1.setStyleSheet(groupbox_style)
275
- self.Step2.setStyleSheet(groupbox_style.replace("Step1","Step2"))
276
- self.Step3.setStyleSheet(groupbox_style.replace("Step1","Step3"))
277
- self.ncbi_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
278
- self.ncbi_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
279
- #navigation page
280
- self.goToPrompt = goToPrompt()
281
- self.goToPrompt.stay.clicked.connect(self.stay)
282
- self.goToPrompt.close.clicked.connect(self.close)
283
-
284
- #loading label
285
- self.loading_window = loading_window()
286
-
287
- self.genbank_checkbox.toggled.connect(self.check_genbank)
288
-
289
- self.first_show = True
290
- scale_ui(self, custom_scale_width=1000, custom_scale_height=750)
291
- self.fontSize = 12
292
- except Exception as e:
293
- show_error("Error initializing NCBI_search_tool class.", e)
294
-
295
- def check_genbank(self):
296
- if self.genbank_checkbox.isChecked():
297
- show_message(
298
- font_size=12,
299
- title="Warning!",
300
- message="The GenBank collection may contain poorly or partially annotated annotation files. We highly recommend using the RefSeq collection if it is available.",
301
- icon=QtWidgets.QMessageBox.Icon.Warning
302
- )
303
- else:
304
- pass
305
-
306
- def go_back(self):
307
- try:
308
- """ Clear table """
309
- self.df = pd.DataFrame() ###Make empty DF
310
- self.model = PandasModel(self.df)
311
- self.proxy = CustomProxyModel(self)
312
- self.proxy.setSourceModel(self.model)
313
- self.ncbi_table.setModel(self.proxy)
314
- self.ncbi_table.verticalHeader().hide()
315
- """ Clear all line edits """
316
- self.organism_line_edit.clear()
317
- self.infra_name_line_edit.clear()
318
- self.ret_max_line_edit.setText("100")
319
- self.infra_name_line_edit.clear()
320
- """ Reset all checkboxes """
321
- self.yes_box.setChecked(False)
322
- self.genbank_checkbox.setChecked(False)
323
- self.refseq_checkbox.setChecked(False)
324
- self.gbff_checkbox.setChecked(False)
325
- self.fna_checkbox.setChecked(False)
326
- """ Hide window """
327
- self.close()
328
- except Exception as e:
329
- show_error("Error in go_back() in ncbi tool.", e)
330
-
331
- @QtCore.pyqtSlot()
332
- def query_db(self):
333
- try:
334
- self.loading_window.loading_bar.setValue(5)
335
- center_ui(self.loading_window)
336
- self.loading_window.show()
337
- QtCore.QCoreApplication.processEvents()
338
-
339
- #setup table
340
- self.comboBox = QtWidgets.QComboBox(self)
341
- self.horizontalHeader = self.ncbi_table.horizontalHeader()
342
- self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked)
343
-
344
- #Build Query commands
345
- retmax = int(self.ret_max_line_edit.text())
346
- if retmax == "":
347
- retmax = 100
348
- org = self.organism_line_edit.text()
349
- term = '"' + org + '"[Organism]'
350
- if self.yes_box.isChecked():
351
- term += ' AND "Complete Genome"[Assembly Level]'
352
- if self.infra_name_line_edit.text() != "":
353
- term += ' AND "' + self.infra_name_line_edit.text() + '"[Infraspecific name]'
354
-
355
- #Search DB for IDs
356
- handle = Entrez.esearch(db="assembly", retmax=retmax, term=term)
357
- content = handle.readlines()
358
- content = "".join(str(content))
359
- #bs_content = BeautifulSoup(content, "lxml")
360
- bs_content = BeautifulSoup(content, "html.parser")
361
-
362
- self.loading_window.loading_bar.setValue(20)
363
- QtCore.QCoreApplication.processEvents()
364
-
365
- #Extract IDs
366
- idlist = bs_content.find('idlist')
367
- ids = idlist.find_all('id')
368
- ids = [i.text for i in ids]
369
-
370
- self.loading_window.loading_bar.setValue(35)
371
- QtCore.QCoreApplication.processEvents()
372
-
373
- # Get Details on IDs
374
- handle = Entrez.esummary(db="assembly", id=','.join(ids))
375
- content = handle.readlines()
376
- handle.close()
377
- content = "".join(str(content))
378
- #bs_content = BeautifulSoup(content, 'lxml')
379
- bs_content = BeautifulSoup(content, "html.parser")
380
-
381
- self.loading_window.loading_bar.setValue(55)
382
-
383
- QtCore.QCoreApplication.processEvents()
384
-
385
- #Prep Data for Table
386
- assembly_name = bs_content.find_all('assemblyname')
387
- genbank_ids = bs_content.find_all('genbank')
388
- refseq_ids = bs_content.find_all('refseq')
389
- assembly_status = bs_content.find_all('assemblystatus')
390
- species_name = bs_content.find_all('speciesname')
391
- temp_strains = bs_content.find_all('infraspecieslist')
392
- assembly_name = [i.text for i in assembly_name]
393
- genbank_ids = [i.text for i in genbank_ids]
394
- refseq_ids = [i.text for i in refseq_ids]
395
- assembly_status = [i.text for i in assembly_status]
396
- species_name = [i.text for i in species_name]
397
- ids = [int(i) for i in ids]
398
- strains = []
399
- for i in range(len(genbank_ids)):
400
- temp_str = str(temp_strains[i])
401
- #temp_str = BeautifulSoup(temp_str, 'lxml')
402
- temp_str = BeautifulSoup(temp_str, 'html.parser')
403
- temp_str = temp_str.find('sub_value')
404
- if temp_str != None:
405
- strains.append(temp_str.text)
406
- else:
407
- strains.append('N/A')
408
-
409
- self.loading_window.loading_bar.setValue(65)
410
- QtCore.QCoreApplication.processEvents()
411
-
412
- #Get ftp links
413
- genbank_links = bs_content.find_all('ftppath_genbank')
414
- refseq_links = bs_content.find_all('ftppath_refseq')
415
- refseq_links = bs_content.find_all('ftppath_refseq')
416
- genbank_links = [i.text for i in genbank_links]
417
- refseq_links = [i.text for i in refseq_links]
418
- self.genbank_ftp_dict = {}
419
- self.refseq_ftp_dict = {}
420
- for i in range(len(ids)):
421
- if genbank_ids[i] == '':
422
- self.genbank_ftp_dict[ids[i]] = ''
423
- else:
424
- self.genbank_ftp_dict[ids[i]] = genbank_links[i] + '/'
425
- if refseq_ids[i] == '':
426
- self.refseq_ftp_dict[ids[i]] = ''
427
- else:
428
- self.refseq_ftp_dict[ids[i]] = refseq_links[i] + '/'
429
-
430
- self.loading_window.loading_bar.setValue(80)
431
- QtCore.QCoreApplication.processEvents()
432
-
433
- #Build dataframe
434
- self.df = pd.DataFrame({'ID': ids,
435
- 'Species Name' : species_name,
436
- 'Strain' : strains,
437
- 'Assembly Name' : assembly_name,
438
- 'GenBank assembly accession': genbank_ids,
439
- 'RefSeq assembly accession': refseq_ids,
440
- 'Assembly Status': assembly_status})
441
-
442
- self.loading_window.loading_bar.setValue(90)
443
- QtCore.QCoreApplication.processEvents()
444
-
445
- #Build table view
446
- self.df.replace('', 'N/A', inplace=True)
447
- self.model = PandasModel(self.df)
448
- self.proxy = CustomProxyModel(self)
449
- self.proxy.setSourceModel(self.model)
450
- self.ncbi_table.setModel(self.proxy)
451
- self.ncbi_table.resizeColumnsToContents()
452
- self.comboBox.addItems(["{0}".format(col) for col in self.model._df.columns])
453
- self.activateWindow()
454
-
455
- #close loading gif
456
- self.loading_window.hide()
457
- self.loading_window.loading_bar.setValue(0)
458
- QtCore.QCoreApplication.processEvents()
459
- except Exception as e:
460
- show_error("Error in query_db() in ncbi tool.", e)
461
-
462
- @QtCore.pyqtSlot(int)
463
- def on_view_horizontalHeader_sectionClicked(self, logicalIndex):
464
- try:
465
- self.logicalIndex = logicalIndex
466
- self.menuValues = QtWidgets.QMenu(self)
467
- self.signalMapper = QtCore.QSignalMapper(self)
468
- self.comboBox.blockSignals(True)
469
- self.comboBox.setCurrentIndex(logicalIndex)
470
- self.comboBox.blockSignals(True)
471
- valuesUnique = self.model._df.iloc[:, logicalIndex].unique()
472
- if logicalIndex == 0:
473
- valuesUnique = ['Sort: 0-9', 'Sort: 9-0']
474
- elif logicalIndex == 2:
475
- valuesUnique = ['Exclude N/A', 'Only N/A', 'Sort: A-Z', 'Sort: Z-A']
476
- elif logicalIndex == 3:
477
- valuesUnique = ['Sort: A-Z', 'Sort: Z-A']
478
- elif logicalIndex == 4 or logicalIndex == 5:
479
- valuesUnique = ['Exclude N/A', 'Only N/A', 'Sort: A-Z', 'Sort: Z-A']
480
-
481
- actionAll = QtWidgets.QAction("All", self)
482
- actionAll.triggered.connect(self.on_actionAll_triggered)
483
- self.menuValues.addAction(actionAll)
484
- self.menuValues.addSeparator()
485
- for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))):
486
- action = QtWidgets.QAction(actionName, self)
487
- self.signalMapper.setMapping(action, actionNumber)
488
- action.triggered.connect(self.signalMapper.map)
489
- self.menuValues.addAction(action)
490
- self.signalMapper.mapped.connect(self.on_signalMapper_mapped)
491
- headerPos = self.ncbi_table.mapToGlobal(self.horizontalHeader.pos())
492
- posY = headerPos.y() + self.horizontalHeader.height()
493
- posX = headerPos.x() + self.horizontalHeader.sectionViewportPosition(logicalIndex)
494
-
495
- self.menuValues.exec_(QtCore.QPoint(posX, posY))
496
- except Exception as e:
497
- show_error("Error in on_view_horizontalHeader_sectionClicked() in ncbi tool.", e)
498
-
499
- @QtCore.pyqtSlot()
500
- def on_actionAll_triggered(self):
501
- try:
502
- filterColumn = self.logicalIndex
503
- self.proxy.setFilter("", filterColumn)
504
- except Exception as e:
505
- show_error("Error in on_actionAll_triggered() in ncbi tool.", e)
506
-
507
- @QtCore.pyqtSlot(int)
508
- def on_signalMapper_mapped(self, i):
509
- try:
510
- indices = self.ncbi_table.selectionModel().selectedRows()
511
- #stringAction = self.signalMapper.mapping(i).text()
512
- if self.logicalIndex == 0:
513
- if i == 0:
514
- self.model.sort(self.logicalIndex, QtCore.Qt.DescendingOrder)
515
- else:
516
- self.model.sort(self.logicalIndex, QtCore.Qt.AscendingOrder)
517
- elif self.logicalIndex == 3:
518
- if i == 0:
519
- self.model.sort(self.logicalIndex, QtCore.Qt.DescendingOrder)
520
- else:
521
- self.model.sort(self.logicalIndex, QtCore.Qt.AscendingOrder)
522
- elif self.logicalIndex == 2 or self.logicalIndex == 4 or self.logicalIndex == 5:
523
- if i == 0:
524
- stringAction = "(?!^N/A$)(^.*$)"
525
- filterColumn = self.logicalIndex
526
- self.proxy.setFilter(stringAction, filterColumn)
527
- elif i == 1:
528
- stringAction = "N/A"
529
- filterColumn = self.logicalIndex
530
- self.proxy.setFilter(stringAction, filterColumn)
531
- elif i == 2:
532
- self.model.sort(self.logicalIndex, QtCore.Qt.DescendingOrder)
533
- else:
534
- self.model.sort(self.logicalIndex, QtCore.Qt.AscendingOrder)
535
- elif self.logicalIndex == 6:
536
- stringAction = self.signalMapper.mapping(i).text()
537
- filterColumn = self.logicalIndex
538
- self.proxy.setFilter(stringAction, filterColumn)
539
- except Exception as e:
540
- show_error("Error in on_signalMapper_mapped() in ncbi tool.", e)
541
-
542
- @QtCore.pyqtSlot()
543
- def download_files_wrapper(self):
544
- try:
545
- self.progressBar.setValue(0)
546
-
547
- #make sure rows are present in table
548
- if self.df.shape[0] == 0:
549
- show_message(
550
- fontSize=self.fontSize,
551
- icon=QtWidgets.QMessageBox.Icon.Critical,
552
- title="No Query Results",
553
- message="Please run an NCBI query to fill the table with results to choose from!"
554
- )
555
- return
556
-
557
- #make sure user has selected at least one row
558
- indices = self.ncbi_table.selectionModel().selectedRows()
559
- if len(indices) == 0:
560
- show_message(
561
- fontSize=self.fontSize,
562
- icon=QtWidgets.QMessageBox.Icon.Critical,
563
- title="No Rows Selected",
564
- message="Please select rows from the table!"
565
- )
566
- return
567
-
568
- threadCount = QtCore.QThreadPool.globalInstance().maxThreadCount() # Get thread count
569
- if len(indices) > threadCount:
570
- show_message(
571
- fontSize=self.fontSize,
572
- icon=QtWidgets.QMessageBox.Icon.Critical,
573
- title="Too Many Selections!",
574
- message="You only have " + str(threadCount) + " threads avaiable to download with.\n\nPlease select " + str(threadCount) + " or fewer rows."
575
- )
576
- return
577
-
578
- #make sure file type is selected
579
- if self.gbff_checkbox.isChecked() == False and self.fna_checkbox.isChecked() == False:
580
- show_message(
581
- fontSize=self.fontSize,
582
- icon=QtWidgets.QMessageBox.Icon.Critical,
583
- title="No File Type Selected",
584
- message="No file type selected. Please select the file types you want to download!"
585
- )
586
- return
587
- self.download_files()
588
- except Exception as e:
589
- show_error("Error in download_files_wrapper() in ncbi tool.", e)
590
-
591
- ### When a new thread is started, spawn a label and progress bar for that thread and add it to the form layout.
592
- def on_thread_start(self, data):
593
- id = data # This is the id for the thread
594
- tmp_lbl = QtWidgets.QLabel()
595
- tmp_lbl.setText("Download(s) Started...")
596
- tmp_bar = QtWidgets.QProgressBar()
597
- self.labels[id] = tmp_lbl # Append thread label to list
598
- self.progressbars[id] = tmp_bar # Append thread label to list
599
- self.formLayout.addRow(tmp_lbl,tmp_bar) # Add label and bar to form layout
600
-
601
- ### When a thread is finished, update its label and progressbar for the last time
602
- def on_thread_finish(self,data):
603
- id = data[0]
604
- my_bool = data[1]
605
- if my_bool: # If thread finished succesfully
606
- self.progressbars[id].setValue(int(self.progressbars[id].maximum())) #Make sure progress bar is full
607
- self.labels[id].setText("Download(s) Complete!") #Make sure progress bar is full
608
- self.progressBar.setValue(int(self.progressBar.value()+1)) # Increment overall progress bar when a thread finishes
609
- QtWidgets.QApplication.processEvents() # Allow the progress bar to update
610
- else:
611
- self.progressBar.setMaximum(int(self.progressBar.maximum()-1)) # Subtract 1 from progress bar to reflect failed thread.
612
- show_message(
613
- fontSize=self.fontSize,
614
- icon=QtWidgets.QMessageBox.Icon.Critical,
615
- title="Link Failed!",
616
- message="Failed to find a valid link for ID: " + str(id) + ". Please make sure this ID is available in the selected database."
617
- )
618
- return
619
-
620
- ### When a file download starts, update the label and progress bar
621
- def on_file_start(self, data):
622
- id = data[0] # This is the id for the thread
623
- prompt = data[1] # This is the prompt to set the label to
624
- maxval = int(data[2]) # This is the file size
625
- self.progressbars[id].setValue(0) # Set max value of progressbar
626
- self.progressbars[id].setMaximum(int(maxval/1e3)) # Set max value of progressbar
627
-
628
- self.labels[id].setText(str(prompt)) # Set label text
629
-
630
- ## Taken from StackOverflow: https://stackoverflow.com/questions/57607072/update-pyqt-progress-from-another-thread-running-ftp-download
631
- def on_progress_ready(self, data):
632
- id = data[0] # This is the id for the thread
633
- val = int(data[1]) # This is the increment
634
- self.progressbars[id].setValue(int(self.progressbars[id].value() + val/1e3)) # Increment progress bar
635
-
636
- ### When a file download finishes, update the label and progress bar and add file name to list
637
- def on_file_finish(self,data):
638
- id = data[0] # This is the id for the thread
639
- prompt = data[1] # This is the prompt to set the label to
640
- file_name = data[2] # This is the filename
641
- self.progressbars[id].setValue(int(self.progressbars[id].maximum())) # Make sure progress bar is set to max after finishing download
642
- self.labels[id].setText(str(prompt))
643
- self.files.append(str(file_name)) # Add filename to list of downloaded files
644
-
645
- def clean_bars(self):
646
- for key in self.progressbars:
647
- label = self.formLayout.labelForField(self.progressbars[key])
648
- if label is not None:
649
- label.deleteLater()
650
- self.progressbars[key].deleteLater()
651
-
652
- self.labels.clear()
653
- self.progressbars.clear()
654
- self.threads.clear()
655
- def clear_layout(self):
656
- for i in reversed(range(self.formLayout.count())):
657
- self.formLayout.itemAt(i).widget().deleteLater()
658
-
659
- ## Taken from StackOverflow: https://stackoverflow.com/questions/57607072/update-pyqt-progress-from-another-thread-running-ftp-download
660
- def download_files(self):
661
- try:
662
- self.labels = {} # Key is the ID, value is the QLabel
663
- self.progressbars = {} # Key is the ID, value is the QProgressBar
664
- self.threads = {} # Key is the ID, value is the QThread
665
- indices = self.ncbi_table.selectionModel().selectedRows()
666
- len_ind = len(indices) # Get number of rows
667
- self.progressBar.setMaximum(int(len_ind)) # Set overall progress bar to be equal to number of rows being downloaded
668
- if len_ind == 0:
669
- return
670
- if self.genbank_checkbox.isChecked() == False and self.refseq_checkbox.isChecked() == False:
671
- return
672
- self.progressLabel.setText("Download(s) Started...") # Update progresslabel
673
- self.files = [] # Initialize list to hold downloaded files
674
- for index in indices: # For selected row(s) in table
675
- NewIndex = self.ncbi_table.model().index(index.row(), 0) # Get index of selected row
676
- id = self.ncbi_table.model().data(NewIndex) # Get ID from selected row
677
- dirs = [] # Initialize list to hold links to ftp directories
678
- if self.genbank_checkbox.isChecked():
679
- genbank_ftp = self.genbank_ftp_dict[int(id)]
680
- dirs.append(genbank_ftp)
681
- else:
682
- refseq_ftp = self.refseq_ftp_dict[int(id)]
683
- dirs.append(refseq_ftp)
684
- for dir in dirs: # Loop through the ftp links
685
- url = str(dir).replace('ftp://ftp.ncbi.nlm.nih.gov', '') # Create new link
686
- downloader = DownloadThread(parent=self,url=url,id=id) # Create a thread for the download
687
- downloader.started.connect(self.on_thread_start) # Connect signal to function
688
- downloader.finished.connect(self.on_thread_finish) # Connect signal to function
689
- downloader.file_started.connect(self.on_file_start)
690
- downloader.file_finished.connect(self.on_file_finish)
691
- downloader.data_progress.connect(self.on_progress_ready) # Connect signal to function
692
- self.threads[url] = downloader # Add thread to dictionary using the url as a key
693
- downloader.start()
694
- """ Make sure all threads are done before checking to see if files were downloaded """
695
- while len([self.threads[t] for t in self.threads if self.threads[t].isRunning()]) > 0:
696
- time.sleep(0.1)
697
- QtWidgets.QApplication.processEvents()
698
- self.progressBar.setValue(int(self.progressBar.maximum())) # Set progressBar to maximum
699
- self.progressLabel.setText("Download(s) Complete!") # Set progressBar to maximum
700
-
701
- self.clean_bars() # Clear out all the bars now that downloading is done
702
-
703
- for i in range(len(self.files)):
704
- self.files[i] = self.files[i].replace('.gz', '')
705
- if platform.system() == 'Windows':
706
- self.files[i] = self.files[i][self.files[i].rfind("\\")+1:]
707
- else:
708
- self.files[i] = self.files[i][self.files[i].rfind("/") + 1:]
709
-
710
- if len(self.files) > 0:
711
- self.rename_files(self.files)
712
- else:
713
- self.clear_layout()
714
- self.clean_bars() # Clear out all the bars since the download failed
715
- show_message(
716
- fontSize = self.fontSize,
717
- icon = QtWidgets.QMessageBox.Icon.Critical,
718
- title = "No Files Downloaded",
719
- message = "No files were downloaded from the selected NCBI files. Please make sure the selected files are available in the database selected."
720
- )
721
- return
722
-
723
- except Exception as e:
724
- show_error("Error in download_files() in ncbi tool.", e)
725
-
726
- @QtCore.pyqtSlot()
727
- def select_all(self):
728
- try:
729
- if self.all_rows.isChecked():
730
- self.ncbi_table.selectAll()
731
- else:
732
- self.ncbi_table.clearSelection()
733
- except Exception as e:
734
- show_error("Error in select_all() in ncbi tool.", e)
735
-
736
- def rename_files(self, files):
737
- try:
738
- msgBox = QtWidgets.QMessageBox()
739
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
740
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
741
- msgBox.setWindowTitle("Rename Files")
742
- msgBox.setText("Would you like to rename the downloaded files?")
743
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
744
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
745
- msgBox.exec()
746
-
747
- if msgBox.result() == QtWidgets.QMessageBox.Yes:
748
- self.rename_window.rename_table.setRowCount(len(files))
749
- cnt = 0
750
- for file in files:
751
- item = QtWidgets.QTableWidgetItem(file)
752
- item.setFlags(QtCore.Qt.ItemIsEnabled)
753
- self.rename_window.rename_table.setItem(cnt, 0, item)
754
-
755
- self.rename_window.rename_table.setCellWidget(cnt, 1, QtWidgets.QLineEdit())
756
- cnt += 1
757
-
758
- header = self.rename_window.rename_table.horizontalHeader()
759
- self.rename_window.rename_table.resizeColumnsToContents()
760
- header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
761
- header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
762
- center_ui(self.rename_window)
763
- self.rename_window.show()
764
- self.rename_window.activateWindow()
765
- else:
766
- GlobalSettings.mainWindow.fill_annotation_dropdown()
767
- self.goToPrompt.show()
768
- self.goToPrompt.activateWindow()
769
- except Exception as e:
770
- show_error("Error in rename_files() in ncbi tool.", e)
771
-
772
- def rename_go_back(self):
773
- try:
774
- self.rename_window.close()
775
- except Exception as e:
776
- show_error("Error in rename_go_back() in ncbi tool.", e)
777
-
778
- def submit_rename(self):
779
- try:
780
- #loop through columns and rename the files
781
- for row in range(self.rename_window.rename_table.rowCount()):
782
- orig = str(self.rename_window.rename_table.item(row, 0).text())
783
- new = str(self.rename_window.rename_table.cellWidget(row, 1).text())
784
- if new != "":
785
- if orig.find(".gbff")!= -1:
786
- if new.find(".") != -1:
787
- new = new[:new.find(".")]
788
- new = new + ".gbff"
789
- elif orig.find(".fna") != -1:
790
- if new.find(".") != -1:
791
- new = new[:new.find(".")]
792
- new = new + ".fna"
793
-
794
- if platform.system() == "Windows":
795
- if new.find(".gbff") != -1:
796
- if os.path.isfile(GlobalSettings.CSPR_DB + "\\GBFF\\" + new) == False:
797
- os.rename(GlobalSettings.CSPR_DB + "\\GBFF\\" + orig, GlobalSettings.CSPR_DB + "\\GBFF\\" + new)
798
- else:
799
- show_message(
800
- fontSize = self.fontSize,
801
- icon = QtWidgets.QMessageBox.Icon.Critical,
802
- title = "Renaming Error",
803
- message = "The filename: " + str(new) + " already exists. Please use a different name."
804
- )
805
- return
806
- else:
807
- if os.path.isfile(GlobalSettings.CSPR_DB + "\\FNA\\" + new) == False:
808
- os.rename(GlobalSettings.CSPR_DB + "\\FNA\\" + orig, GlobalSettings.CSPR_DB + "\\FNA\\" + new)
809
- else:
810
- show_message(
811
- fontSize = self.fontSize,
812
- icon = QtWidgets.QMessageBox.Icon.Critical,
813
- title = "Renaming Error",
814
- message = "The filename: " + str(new) + " already exists. Please use a different name."
815
- )
816
- return
817
- else:
818
- #unix cannot have spaces in paths
819
- new = new.replace(" ","")
820
- if new.find(".gbff") != -1:
821
- if os.path.isfile(GlobalSettings.CSPR_DB + "/GBFF/" + new) == False:
822
- os.rename(GlobalSettings.CSPR_DB + "/GBFF/" + orig, GlobalSettings.CSPR_DB + "/GBFF/" + new)
823
- else:
824
- show_message(
825
- fontSize = self.fontSize,
826
- icon = QtWidgets.QMessageBox.Icon.Critical,
827
- title = "Renaming Error",
828
- message = "The filename: " + str(new) + " already exists. Please use a different name."
829
- )
830
- return
831
- else:
832
- if os.path.isfile(GlobalSettings.CSPR_DB + "/FNA/" + new) == False:
833
- os.rename(GlobalSettings.CSPR_DB + "/FNA/" + orig, GlobalSettings.CSPR_DB + "/FNA/" + new)
834
- else:
835
- show_message(
836
- fontSize = self.fontSize,
837
- icon = QtWidgets.QMessageBox.Icon.Critical,
838
- title = "Renaming Error",
839
- message = "The filename: " + str(new) + " already exists. Please use a different name."
840
- )
841
- return
842
-
843
- self.rename_window.rename_table.setRowCount(0)
844
- self.rename_window.close()
845
- GlobalSettings.mainWindow.fill_annotation_dropdown()
846
- center_ui(self.goToPrompt)
847
- self.goToPrompt.show()
848
- self.goToPrompt.activateWindow()
849
- except Exception as e:
850
- show_error("Error in submit_rename() in ncbi tool.", e)
851
-
852
- def stay(self):
853
- try:
854
- self.goToPrompt.hide()
855
- except Exception as e:
856
- show_error("Error in stay() in ncbi tool.", e)
857
-
858
- def close(self):
859
- try:
860
- self.hide()
861
- self.goToPrompt.hide()
862
- except Exception as e:
863
- show_error("Error in close() in ncbi tool.", e)
864
-
865
- class goToPrompt(QtWidgets.QMainWindow):
866
- def __init__(self):
867
- try:
868
- super(goToPrompt, self).__init__()
869
- uic.loadUi(GlobalSettings.appdir + 'ui/ncbi_nav_page.ui', self)
870
- self.setWindowTitle("Navigate")
871
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
872
- self.label.setText("Successfully downloaded file(s) to the CASPERdb directory:\n" + GlobalSettings.CSPR_DB)
873
- self.label.setAlignment(QtCore.Qt.AlignCenter)
874
- groupbox_style = """
875
- QGroupBox:title{subcontrol-origin: margin;
876
- left: 10px;
877
- padding: 0 5px 0 5px;}
878
- QGroupBox#groupBox{border: 2px solid rgb(111,181,110);
879
- border-radius: 9px;
880
- font: bold 14pt 'Arial';
881
- margin-top: 10px;}"""
882
- self.groupBox.setStyleSheet(groupbox_style)
883
-
884
- # self.scaleUI()
885
- scale_ui(self, custom_scale_width=575, custom_scale_height=225)
886
- except Exception as e:
887
- show_error("Error initializing goToPrompt class in ncbi tool.", e)
888
-
889
- class rename_window(QtWidgets.QMainWindow):
890
- def __init__(self):
891
- try:
892
- super(rename_window, self).__init__()
893
- uic.loadUi(GlobalSettings.appdir + "ui/ncbi_rename_window.ui", self)
894
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
895
- self.setWindowTitle("Rename Files")
896
- self.rename_table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
897
- self.rename_table.setColumnCount(2)
898
- self.rename_table.setHorizontalHeaderLabels(['Original Filename', 'New Filename'])
899
-
900
- scale_ui(self, custom_scale_width=575, custom_scale_height=300)
901
- except Exception as e:
902
- show_error("Error initializing rename_window class in ncbi tool.", e)
903
-
904
- #loading window UI class for when data is loading
905
- class loading_window(QtWidgets.QMainWindow):
906
- def __init__(self):
907
- try:
908
- super(loading_window, self).__init__()
909
- uic.loadUi(GlobalSettings.appdir + "ui/loading_data_form.ui", self)
910
- self.loading_bar.setValue(0)
911
- self.setWindowTitle("Loading NCBI Data")
912
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
913
- scale_ui(self, custom_scale_width=450, custom_scale_height=125)
914
- except Exception as e:
915
- show_error("Error initializing loading_window class in ncbi tool.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
controllers/populationAnalysis.py DELETED
@@ -1,929 +0,0 @@
1
- from PyQt5 import QtWidgets, Qt, QtGui, QtCore, uic
2
- from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
3
- from matplotlib.figure import Figure
4
- import models.GlobalSettings as GlobalSettings
5
- import os
6
- import utils.Algorithms as Algorithms
7
- import numpy as np
8
- from PyQt5.QtWidgets import *
9
- import gzip
10
- import sqlite3
11
- import itertools
12
- import matplotlib.patches as patches
13
- import mplcursors
14
- import copy
15
- from utils.ui import show_error, scale_ui, center_ui, show_message
16
-
17
- logger = GlobalSettings.logger
18
-
19
- class Pop_Analysis(QtWidgets.QMainWindow):
20
- def __init__(self):
21
- try:
22
- super(Pop_Analysis, self).__init__()
23
- uic.loadUi(GlobalSettings.appdir + 'ui/pop.ui', self)
24
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
25
- self.goBackButton.clicked.connect(self.go_back)
26
- self.analyze_button.clicked.connect(self.pre_analyze)
27
- self.clear_Button.clicked.connect(self.clear)
28
- self.export_button.clicked.connect(self.export_tool)
29
- self.sq = Algorithms.SeqTranslate()
30
- self.ref_para_list = list()
31
- self.mode = 0
32
- self.find_locs_button.clicked.connect(self.find_locations)
33
- self.clear_loc_button.clicked.connect(self.clear_loc_table)
34
- self.names = []
35
- self.names_venn = []
36
-
37
- """ Colormap Graph initialization """
38
- self.colormap_layout = QtWidgets.QVBoxLayout()
39
- self.colormap_layout.setContentsMargins(0,0,0,0)
40
- self.colormap_canvas = MplCanvas(self) ###Initialize new Canvas
41
-
42
- groupbox_style = """
43
- QGroupBox:title{subcontrol-origin: margin;
44
- left: 10px;
45
- padding: 0 5px 0 15px;}
46
- QGroupBox#groupBox{border: 2px solid rgb(111,181,110);
47
- border-radius: 9px;
48
- font: bold 14pt 'Arial';
49
- margin-top: 10px;}"""
50
- self.groupBox.setStyleSheet(groupbox_style)
51
- self.groupBox_2.setStyleSheet(groupbox_style.replace("groupBox","groupBox_2"))
52
-
53
- #organism table
54
- self.org_Table.setColumnCount(1)
55
- self.org_Table.setShowGrid(False)
56
- self.org_Table.setHorizontalHeaderLabels(["Organism"])
57
- self.org_Table.horizontalHeader().setSectionsClickable(True)
58
- self.org_Table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
59
- self.org_Table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
60
- self.org_Table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
61
- self.org_Table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
62
- #self.org_Table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
63
-
64
- #top-right table
65
- self.table2.setColumnCount(9)
66
- self.table2.setShowGrid(False)
67
- self.table2.setHorizontalHeaderLabels(["Seed","% Coverage","Total Repeats","Avg. Repeats/Scaffold", "Consensus Sequence", "% Consensus", "Score","PAM", "Strand"])
68
- self.table2.horizontalHeader().setSectionsClickable(True)
69
- self.table2.horizontalHeader().sectionClicked.connect(self.table2_sorting)
70
- self.table2.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
71
- self.table2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
72
- self.table2.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
73
- self.table2.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
74
- self.table2.resizeColumnsToContents()
75
-
76
- # Finder table
77
- self.loc_finder_table.setColumnCount(5)
78
- self.loc_finder_table.setShowGrid(False)
79
- self.loc_finder_table.setHorizontalHeaderLabels(["Seed ID", "Sequence", "Organism", "Scaffold", "Location"])
80
- self.loc_finder_table.horizontalHeader().setSectionsClickable(True)
81
- self.loc_finder_table.horizontalHeader().sectionClicked.connect(self.loc_table_sorter)
82
- self.loc_finder_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
83
- self.loc_finder_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
84
- #self.loc_finder_table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
85
- # self.loc_finder_table.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
86
- # self.loc_finder_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
87
- self.loc_finder_table.resizeColumnsToContents()
88
-
89
- #custom seed search
90
- self.query_seed_button.clicked.connect(self.custom_seed_search)
91
-
92
- self.total_org_number = 0
93
-
94
- self.switcher_table2 = [1, 1, 1, 1, 1, 1, 1, 1,
95
- 1] # for keeping track of where we are in the sorting clicking for each column
96
- self.switcher_loc_table = [1, 1, 1, 1, 1]
97
-
98
- #Initialize variables
99
- self.index_to_cspr = {}
100
- self.index_to_db = {}
101
- self.name_to_db = {}
102
- self.cspr_files = []
103
- self.seeds = []
104
-
105
- self.loading_window = loading_window()
106
-
107
- self.first_show = True
108
- scale_ui(self, base_width=1920, base_height=1080, font_size=12, header_font_size=30)
109
-
110
- except Exception as e:
111
- show_error("Error initializing population analysis.", e)
112
-
113
- #export shared seed table to csv function
114
- def export_tool(self):
115
- try:
116
- select_items = self.table2.selectedItems()
117
-
118
- if len(select_items) <= 0:
119
- show_message(
120
- fontSize=12,
121
- icon=QtWidgets.QMessageBox.Icon.Critical,
122
- title="Nothing Selected",
123
- message="No targets were highlighted. Please highlight the targets you want to be exported to a CSV File!"
124
- )
125
- return
126
-
127
- GlobalSettings.mainWindow.export_tool_window.launch(select_items,"pa")
128
- except Exception as e:
129
- show_error("Error in export_tool() in population analysis.", e)
130
-
131
- # this function calls the popParser function and fills all the tables
132
- def pre_analyze(self):
133
- try:
134
- #clear saved filenames
135
- self.cspr_files = []
136
- self.db_files = []
137
- self.rows = []
138
-
139
- #get selected indexes
140
- selected_indexes = self.org_Table.selectionModel().selectedRows()
141
-
142
- if len(selected_indexes) == 0:
143
- show_message(
144
- fontSize=12,
145
- icon=QtWidgets.QMessageBox.Icon.Critical,
146
- title="Error",
147
- message="Please select CSPR file(s) for analysis."
148
- )
149
- return
150
-
151
- #get cspr and db filenames
152
- for index in sorted(selected_indexes):
153
- self.rows.append(index.row() + 1)
154
- self.cspr_files.append(self.index_to_cspr[index.row()])
155
- self.db_files.append(self.index_to_db[index.row()])
156
-
157
- self.get_org_names()
158
- self.fill_data()
159
- except Exception as e:
160
- show_error("Error in pre_analyze() in population analysis.", e)
161
-
162
- def launch(self):
163
- try:
164
- self.get_data()
165
- except Exception as e:
166
- show_error("Error in launch() in population analysis.", e)
167
-
168
- #responsible for calling all loading/analysis functions for loading the shared seeds table and generating the heatmap based on selected organisms
169
- def get_data(self):
170
- try:
171
- self.fillEndo()
172
- except Exception as e:
173
- show_error("Error in get_data() in population analysis.", e)
174
-
175
- # this function opens CASPERinfo and builds the dropdown menu of selectable endonucleases
176
- def fillEndo(self):
177
- try:
178
- try:
179
- self.endoBox.currentIndexChanged.disconnect()
180
- except:
181
- pass
182
-
183
- self.Endos = {}
184
- self.endoBox.clear()
185
- f = open(GlobalSettings.appdir + 'CASPERinfo')
186
- while True:
187
- line = f.readline()
188
- if line.startswith('ENDONUCLEASES'):
189
- while True:
190
- line = f.readline()
191
- if (line[0] == "-"):
192
- break
193
- line_tokened = line.split(";")
194
- endo = line_tokened[0]
195
- # Checking to see if there is more than one pam sequence in the list
196
- if line_tokened[1].find(",") != -1:
197
- p_pam = line_tokened[1].split(",")[0]
198
- else:
199
- p_pam = line_tokened[1]
200
- default_five_length = line_tokened[2]
201
- default_seed_length = line_tokened[3]
202
- default_three_length = line_tokened[4]
203
- self.Endos[endo + " PAM: " + p_pam] = (endo, p_pam, default_five_length, default_seed_length, default_three_length)
204
-
205
- break
206
- f.close()
207
- self.endoBox.addItems(self.Endos.keys())
208
- self.endoBox.currentIndexChanged.connect(self.change_endo)
209
- self.change_endo()
210
- except Exception as e:
211
- show_error("Error in fillEndo() in population analysis.", e)
212
-
213
- #event handler for updating the organism options based on the endo selected
214
- def change_endo(self):
215
- try:
216
- self.org_Table.clearContents()
217
- self.org_Table.setRowCount(0)
218
- onlyfiles = [f for f in os.listdir(GlobalSettings.CSPR_DB) if os.path.isfile(os.path.join(GlobalSettings.CSPR_DB, f))]
219
- index = 0
220
- for file in onlyfiles:
221
- if file.find('.cspr') != -1:
222
- endo = file[file.rfind('_') + 1:file.find('.cspr')]
223
- if endo == self.Endos[self.endoBox.currentText()][0]:
224
-
225
- # increase row count
226
- self.org_Table.setRowCount(index + 1)
227
-
228
- # open .cspr file and get genome name
229
- f = open(file, 'r')
230
- line = f.readline()
231
- f.close()
232
- line = str(line)
233
- line = line.split(":")[-1].strip()
234
- orgName = line
235
- # add genome name to table
236
- tabWidget = QtWidgets.QTableWidgetItem(orgName)
237
- tabWidget.setTextAlignment(QtCore.Qt.AlignVCenter)
238
- self.org_Table.setItem(index, 0, tabWidget)
239
-
240
- # store cspr and db file information for later
241
- self.index_to_cspr[index] = file
242
- db_file = file.replace(".cspr", "")
243
- db_file += "_repeats.db"
244
- self.index_to_db[index] = db_file
245
-
246
- # incrase row index
247
- index += 1
248
-
249
- if index == 0:
250
- self.org_Table.clearContents()
251
- self.org_Table.setRowCount(0)
252
-
253
- self.org_Table.resizeColumnsToContents()
254
- except Exception as e:
255
- show_error("Error in change_endo() in population analysis.", e)
256
-
257
- #fills shared seed table with data from analysis
258
- def fill_data(self):
259
- try:
260
- #update progress bar
261
- self.loading_window.loading_bar.setValue(5)
262
- center_ui(self.loading_window)
263
- self.loading_window.show()
264
- QtCore.QCoreApplication.processEvents()
265
-
266
- #prep table
267
- self.total_org_number = len(self.cspr_files)
268
- self.table2.setRowCount(0)
269
- self.loading_window.loading_bar.setValue(10)
270
- index = 0
271
-
272
- self.seeds = self.get_shared_seeds(self.db_files, True)
273
-
274
- try:
275
- os.remove(GlobalSettings.appdir + "temp_join.db")
276
- except:
277
- pass
278
-
279
- no_seeds = False
280
-
281
- if(len(self.seeds) == 0):
282
- no_seeds = True
283
-
284
- #QtCore.QCoreApplication.processEvents()
285
-
286
- #retrieve data on shared seeds
287
- if no_seeds == False:
288
- increase_val = float(15 / len(self.seeds))
289
- running_val = self.loading_window.loading_bar.value()
290
- self.loading_window.info_label.setText("Parsing Seed Data")
291
- self.counts = []
292
- for seed in self.seeds:
293
- # increase row count
294
- self.table2.setRowCount(index + 1)
295
-
296
- # push seed to table
297
- table_seed = QtWidgets.QTableWidgetItem()
298
- table_seed.setData(QtCore.Qt.EditRole, seed)
299
- table_seed.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
300
- self.table2.setItem(index, 0, table_seed)
301
-
302
- total_count = 0
303
- org_count = 0
304
- threes = []
305
- fives = []
306
- scores = []
307
- pams = []
308
- locs = []
309
-
310
- for db_file in self.db_files:
311
- conn = sqlite3.connect(db_file)
312
- c = conn.cursor()
313
- data = c.execute("SELECT count, three, five, pam, score, location FROM repeats WHERE seed = ? ",(seed,)).fetchone()
314
- if data != None:
315
- data = list(data)
316
- print(data)
317
- org_count += 1
318
- total_count += int(data[0])
319
- threes += data[1].split(",")
320
- fives += data[2].split(",")
321
- pams += data[3].split(",")
322
- scores += data[4].split(",")
323
- print(scores)
324
- locs += data[5].split(",")
325
-
326
- self.counts.append(total_count)
327
-
328
- if len(threes) < len(fives):
329
- for i in range(len(fives) - len(threes)):
330
- threes.append('')
331
-
332
- elif len(fives) < len(threes):
333
- for i in range(len(threes) - len(fives)):
334
- fives.append('')
335
-
336
- majority_index = 0
337
- three_prime, five_prime, both_prime = False, False, False
338
- if threes[0] == '':
339
- majority = max(set(fives), key=fives.count)
340
- majority_index = fives.index(majority)
341
- five_prime = True
342
- elif fives[0] == '':
343
- majority = max(set(threes), key=threes.count)
344
- majority_index = threes.index(majority)
345
- three_prime = True
346
- else:
347
- #account for both 3 and 5 present
348
- threes_and_fives = []
349
- for i in range(len(threes)):
350
- threes_and_fives.append(threes[i] + fives[i])
351
- majority = max(set(threes_and_fives), key=threes_and_fives.count)
352
- majority_index = threes_and_fives.index(majority)
353
- both_prime = True
354
-
355
- # push percent coverage
356
- perc_cov = QtWidgets.QTableWidgetItem()
357
- coverage = (org_count / len(self.db_files)) * 100
358
- coverage = float("%.2f" % coverage)
359
- perc_cov.setData(QtCore.Qt.EditRole, coverage)
360
- perc_cov.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
361
- self.table2.setItem(index, 1, perc_cov)
362
-
363
- # push total count
364
- table_count = QtWidgets.QTableWidgetItem()
365
- table_count.setData(QtCore.Qt.EditRole, total_count)
366
- table_count.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
367
- self.table2.setItem(index, 2, table_count)
368
-
369
- # push avg repeat
370
- avg_rep = QtWidgets.QTableWidgetItem()
371
- avg_rep_per_scaff = total_count / org_count
372
- avg_rep_per_scaff = float("%.2f" % avg_rep_per_scaff)
373
- avg_rep.setData(QtCore.Qt.EditRole, avg_rep_per_scaff)
374
- avg_rep.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
375
- self.table2.setItem(index, 3, avg_rep)
376
-
377
- # push seq
378
- seq = QtWidgets.QTableWidgetItem()
379
- seq.setData(QtCore.Qt.EditRole, fives[majority_index] + seed + threes[majority_index])
380
- seq.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
381
- self.table2.setItem(index, 4, seq)
382
-
383
- # push percent consensus
384
- perc_cons = QtWidgets.QTableWidgetItem()
385
- percent_consensus = 0
386
- if five_prime == True:
387
- percent_consensus = (fives.count(fives[majority_index]) / len(fives)) * 100
388
- elif three_prime == True:
389
- percent_consensus = (threes.count(threes[majority_index]) / len(threes)) * 100
390
- elif both_prime:
391
- percent_consensus = (threes_and_fives.count(threes_and_fives[majority_index]) / len(threes_and_fives)) * 100
392
-
393
- percent_consensus = float("%.2f" % percent_consensus)
394
- perc_cons.setData(QtCore.Qt.EditRole, percent_consensus)
395
- perc_cons.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
396
- self.table2.setItem(index, 5, perc_cons)
397
-
398
- # push score
399
- score = QtWidgets.QTableWidgetItem()
400
- score.setData(QtCore.Qt.EditRole, scores[majority_index])
401
- score.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
402
- self.table2.setItem(index, 6, score)
403
-
404
- # push PAM
405
- pam = QtWidgets.QTableWidgetItem()
406
- pam.setData(QtCore.Qt.EditRole, pams[majority_index])
407
- pam.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
408
- self.table2.setItem(index, 7, pam)
409
-
410
- # push strand
411
- strand_val = ""
412
- if int(locs[majority_index]) < 0:
413
- strand_val = "-"
414
- else:
415
- strand_val = "+"
416
-
417
- strand = QtWidgets.QTableWidgetItem()
418
- strand.setData(QtCore.Qt.EditRole, strand_val)
419
- strand.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
420
- self.table2.setItem(index, 8, strand)
421
-
422
- index += 1
423
- running_val += increase_val
424
- self.loading_window.loading_bar.setValue(int(running_val))
425
-
426
- self.table2.resizeColumnsToContents()
427
- self.loading_window.loading_bar.setValue(25)
428
- if len(self.db_files) > 1:
429
- self.plot_3D_graph()
430
- else:
431
- self.colormap_canvas.figure.set_visible(False)
432
-
433
- self.loading_window.loading_bar.setValue(100)
434
- self.loading_window.hide()
435
- QtCore.QCoreApplication.processEvents()
436
- except Exception as e:
437
- show_error("Error in fill_data() in population analysis.", e)
438
-
439
- #function to allow user to search for a specific seed amongst the organisms analyzed
440
- def custom_seed_search(self):
441
- try:
442
- seeds = str(self.seed_input.text())
443
- seeds = seeds.replace(" ","")
444
- seeds = seeds.upper()
445
- seeds = seeds.split(",")
446
-
447
- if len(seeds) == 1:
448
- if seeds[0] == "":
449
- self.pre_analyze()
450
- return
451
-
452
- # update progress bar
453
- self.loading_window.loading_bar.setValue(5)
454
- self.loading_window.show()
455
- QtCore.QCoreApplication.processEvents()
456
-
457
- # prep table
458
- self.total_org_number = len(self.cspr_files)
459
- self.loading_window.loading_bar.setValue(10)
460
- index = 0
461
-
462
- if (len(seeds) == 0):
463
- self.loading_window.hide()
464
- return
465
-
466
- if len(self.seeds) == 0:
467
- self.loading_window.hide()
468
- show_message(
469
- fontSize=12,
470
- icon=QtWidgets.QMessageBox.Icon.Critical,
471
- title="Error",
472
- message="No analysis has been run to be able to search for a specific seed."
473
- )
474
- return
475
-
476
- increase_val = float(15 / len(self.seeds))
477
- running_val = self.loading_window.loading_bar.value()
478
- self.loading_window.info_label.setText("Parsing Seed Data")
479
- # QtCore.QCoreApplication.processEvents()
480
-
481
- self.table2.setRowCount(0)
482
-
483
- # retrieve data on shared seeds
484
- self.counts = []
485
- for seed in seeds:
486
- total_count = 0
487
- org_count = 0
488
- threes = []
489
- fives = []
490
- scores = []
491
- pams = []
492
- locs = []
493
- none_data = True
494
- for db_file in self.db_files:
495
- conn = sqlite3.connect(db_file)
496
- c = conn.cursor()
497
- data = c.execute("SELECT count, three, five, pam, score, location FROM repeats WHERE seed = ?",
498
- (seed,)).fetchone()
499
- if data != None:
500
- none_data = False
501
- data = list(data)
502
- org_count += 1
503
- total_count += int(data[0])
504
- threes += data[1].split(",")
505
- fives += data[2].split(",")
506
- pams += data[3].split(",")
507
- scores += data[4].split(",")
508
- locs += data[5].split(",")
509
-
510
- if none_data == True:
511
- self.loading_window.hide()
512
- show_message(
513
- fontSize=12,
514
- icon=QtWidgets.QMessageBox.Icon.Critical,
515
- title="Seed Error",
516
- message=seed + " : No such seed exists in the repeats section of any organism selected."
517
- )
518
- return
519
-
520
- else:
521
-
522
- # increase row count
523
- self.table2.setRowCount(index + 1)
524
-
525
- # push seed to table
526
- table_seed = QtWidgets.QTableWidgetItem()
527
- table_seed.setData(QtCore.Qt.EditRole, seed)
528
- table_seed.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
529
- self.table2.setItem(index, 0, table_seed)
530
-
531
- self.counts.append(total_count)
532
-
533
- if len(threes) < len(fives):
534
- for i in range(len(fives) - len(threes)):
535
- threes.append('')
536
- elif len(fives) < len(threes):
537
- for i in range(len(threes) - len(fives)):
538
- fives.append('')
539
-
540
- majority_index = 0
541
- three_prime, five_prime, both_prime = False, False, False
542
- if threes[0] == '':
543
- majority = max(set(fives), key=fives.count)
544
- majority_index = fives.index(majority)
545
- five_prime = True
546
- elif fives[0] == '':
547
- majority = max(set(threes), key=threes.count)
548
- majority_index = threes.index(majority)
549
- three_prime = True
550
- else:
551
- # account for both 3 and 5 present
552
- threes_and_fives = []
553
- for i in range(len(threes)):
554
- threes_and_fives.append(threes[i] + fives[i])
555
- majority = max(set(threes_and_fives), key=threes_and_fives.count)
556
- majority_index = threes_and_fives.index(majority)
557
- both_prime = True
558
-
559
- # push percent coverage
560
- perc_cov = QtWidgets.QTableWidgetItem()
561
- coverage = (org_count / len(self.db_files)) * 100
562
- coverage = float("%.2f" % coverage)
563
- perc_cov.setData(QtCore.Qt.EditRole, coverage)
564
- perc_cov.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
565
- self.table2.setItem(index, 1, perc_cov)
566
-
567
- # push total count
568
- table_count = QtWidgets.QTableWidgetItem()
569
- table_count.setData(QtCore.Qt.EditRole, total_count)
570
- table_count.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
571
- self.table2.setItem(index, 2, table_count)
572
-
573
- # push avg repeat
574
- avg_rep = QtWidgets.QTableWidgetItem()
575
- avg_rep_per_scaff = total_count / org_count
576
- avg_rep_per_scaff = float("%.2f" % avg_rep_per_scaff)
577
- avg_rep.setData(QtCore.Qt.EditRole, avg_rep_per_scaff)
578
- avg_rep.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
579
- self.table2.setItem(index, 3, avg_rep)
580
-
581
- # push seq
582
- seq = QtWidgets.QTableWidgetItem()
583
- seq.setData(QtCore.Qt.EditRole, fives[majority_index] + seed + threes[majority_index])
584
- seq.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
585
- self.table2.setItem(index, 4, seq)
586
-
587
- # push percent consensus
588
- perc_cons = QtWidgets.QTableWidgetItem()
589
- percent_consensus = 0
590
- if five_prime == True:
591
- percent_consensus = (fives.count(fives[majority_index]) / len(fives)) * 100
592
- elif three_prime == True:
593
- percent_consensus = (threes.count(threes[majority_index]) / len(threes)) * 100
594
- elif both_prime:
595
- percent_consensus = (threes_and_fives.count(threes_and_fives[majority_index]) / len(threes_and_fives)) * 100
596
- percent_consensus = float("%.2f" % percent_consensus)
597
- perc_cons.setData(QtCore.Qt.EditRole, percent_consensus)
598
- perc_cons.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
599
- self.table2.setItem(index, 5, perc_cons)
600
-
601
- # push score
602
- score = QtWidgets.QTableWidgetItem()
603
- score.setData(QtCore.Qt.EditRole, scores[majority_index])
604
- score.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
605
- self.table2.setItem(index, 6, score)
606
-
607
- # push PAM
608
- pam = QtWidgets.QTableWidgetItem()
609
- pam.setData(QtCore.Qt.EditRole, pams[majority_index])
610
- pam.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
611
- self.table2.setItem(index, 7, pam)
612
-
613
- # push strand
614
- strand_val = ""
615
- if int(locs[majority_index]) < 0:
616
- strand_val = "-"
617
- else:
618
- strand_val = "+"
619
-
620
- strand = QtWidgets.QTableWidgetItem()
621
- strand.setData(QtCore.Qt.EditRole, strand_val)
622
- strand.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
623
- self.table2.setItem(index, 8, strand)
624
-
625
- index += 1
626
- running_val += increase_val
627
- self.loading_window.loading_bar.setValue(int(running_val))
628
-
629
- self.table2.resizeColumnsToContents()
630
- self.loading_window.hide()
631
- QtCore.QCoreApplication.processEvents()
632
- except Exception as e:
633
- show_error("Error in custom_seed_search() in population analysis.", e)
634
-
635
- #db_files is an array of database files for the organisms that will be looked at for shared seeds
636
- def get_shared_seeds(self, db_files, limit=False):
637
- try:
638
- aliases = []
639
-
640
- #get db attachment aliases
641
- for i in range(1, len(db_files) + 1):
642
- aliases.append("main" + str(i))
643
-
644
- #memory connections for inner join on db files to hold what seeds are shared
645
- new_conn = sqlite3.connect(GlobalSettings.appdir + "temp_join.db")
646
- new_c = new_conn.cursor()
647
- new_c.execute("PRAGMA synchronous = OFF;")
648
- new_c.execute("PRAGMA journal_mode = OFF;")
649
- new_c.execute("PRAGMA locking_mode = EXCLUSIVE;")
650
- new_c.execute("DROP TABLE IF EXISTS repeats;")
651
- new_c.execute("VACUUM;")
652
- new_c.execute("DROP TABLE IF EXISTS join_results;")
653
- new_c.execute("CREATE table join_results (seed TEXT PRIMARY KEY);")
654
-
655
- #attach each db file with an alias
656
- for i in range(len(db_files)):
657
- new_c.execute("ATTACH DATABASE '" + db_files[i] + "' AS " + aliases[i] + ";")
658
-
659
- # start transaction
660
- new_c.execute("BEGIN TRANSACTION;")
661
-
662
- sql_inner_join = "INSERT into main.join_results select main1.repeats.seed from main1.repeats "
663
-
664
- for i in range(len(aliases[:-1])):
665
- sql_inner_join += "inner join " + aliases[i + 1] + ".repeats on "
666
- sql_inner_join += aliases[i] + ".repeats.seed = " + aliases[i + 1] + ".repeats.seed "
667
-
668
- #execute inner join
669
- new_c.execute(sql_inner_join)
670
-
671
- #get shared data
672
- if limit == False:
673
- shared_seeds = new_c.execute("select count(*) from join_results").fetchall()
674
- return shared_seeds
675
- else:
676
- shared_seeds = new_c.execute("select * from join_results limit 0,1000").fetchall()
677
-
678
- #end transaction
679
- new_c.execute("END TRANSACTION;")
680
-
681
- #close memory db
682
- new_c.close()
683
- new_conn.close()
684
-
685
- #parse shared seeds into self.seeds
686
- seeds = []
687
- for tup in shared_seeds:
688
- seeds.append(tup[0])
689
-
690
- return seeds
691
-
692
- except Exception as e:
693
- show_error("Error in get_shared_seeds() in population analysis.", e)
694
-
695
- #get the names of organism in current directory
696
- def get_org_names(self):
697
- try:
698
- self.org_names = {}
699
- for file in self.cspr_files:
700
- with open(file, "r") as f:
701
- line = f.readline()
702
- buf = str(line)
703
- buf = buf.strip()
704
- org_name = buf.replace("GENOME: ", "")
705
-
706
- line = f.readline()
707
- buf = str(line)
708
- kstats = buf.replace("KARYSTATS: ", "")
709
- kstats = kstats.split(",")
710
- self.org_names[org_name] = len(kstats) - 1
711
- except Exception as e:
712
- show_error("Error in get_org_names() in population analysis.", e)
713
-
714
- #plot the heatmap graph
715
- def plot_3D_graph(self):
716
- try:
717
- for i in reversed(range(self.colormap_layout.count())): ### Clear out old widges in layout
718
- self.colormap_layout.itemAt(i).widget().setParent(None)
719
-
720
- self.colormap_canvas = MplCanvas(self, width=5, height=3, dpi=self.dpi) ###Initialize new Canvas
721
- self.colormap_layout.addWidget(self.colormap_canvas) ### Add canvas to colormap layout
722
- self.colormap_figure.setLayout(self.colormap_layout) ### Add colormap layout to colormap plot widget
723
-
724
- # self.colormap_canvas.axes.clear()
725
- # try:
726
- # self.colormap_canvas.cbar.remove()
727
- # except:
728
- # None
729
- # self.colormap_canvas.figure.set_visible(True)
730
-
731
- rows, cols = (self.total_org_number, self.total_org_number)
732
- arr = [[0 for i in range(cols)] for j in range(rows)]
733
-
734
- self.names = list(self.org_names.keys())
735
-
736
- for pair in list(itertools.combinations(self.db_files, 2)):
737
- shared_seeds = list(self.get_shared_seeds(list(pair), False)[0])[0]
738
-
739
- arr[self.db_files.index(pair[0])][self.db_files.index(pair[1])] += int(shared_seeds)
740
- arr[self.db_files.index(pair[1])][self.db_files.index(pair[0])] += int(shared_seeds)
741
-
742
- for i in range(len(arr)):
743
- conn = sqlite3.connect(self.db_files[i])
744
- c = conn.cursor()
745
- arr[i][i] = int(list(c.execute("select count(*) from repeats;").fetchall()[0])[0])
746
- c.close()
747
- conn.close()
748
-
749
- labels = copy.deepcopy(arr)
750
-
751
- for i in range(len(arr)):
752
- arr[i][i] = 0
753
-
754
- ax = self.colormap_canvas.axes
755
- im = self.colormap_canvas.axes.imshow(arr, cmap='summer')
756
- self.colormap_canvas.cbar = self.colormap_canvas.axes.figure.colorbar(im, ax=self.colormap_canvas.axes)
757
- self.colormap_canvas.cbar.ax.set_ylabel("", rotation=-90, va="bottom",fontsize=8)
758
- cursor = mplcursors.cursor(im, hover=True)
759
- @cursor.connect("add")
760
- def on_add(sel):
761
- sel.annotation.arrow_patch.set(arrowstyle="simple", fc="white", alpha=.5)
762
- sel.annotation.set_bbox(None)
763
- i,j = sel.target.index
764
- sel.annotation.set_text(labels[i][j])
765
-
766
- ax.set_xticks(np.arange(len(arr)))
767
- ax.set_yticks(np.arange(len(arr)))
768
-
769
- def plotCellGrid(data, ax=None, **kwargs):
770
- for x in range(data[0]):
771
- for y in range(data[1]):
772
- rect = patches.Rectangle((x - .5, y - .5), 1, 1, fill=False, **kwargs)
773
- ax.add_patch(rect)
774
-
775
- #get labels based on org table rows
776
- ax.set_xticklabels(self.rows)
777
- ax.set_yticklabels(self.rows)
778
- ax.set_xlabel("Organism", fontsize = 10)
779
- ax.set_ylabel("Organism", fontsize = 10)
780
- ax.tick_params(axis='both', which='major', labelsize=8)
781
- plotCellGrid([len(self.rows), len(self.rows)], ax, color="black", linewidth=1)
782
-
783
- self.colormap_canvas.draw()
784
- except Exception as e:
785
- show_error("Error in plot_3D_graph() in population analysis.", e)
786
-
787
- #find the locations of selected seeds to load into the location table
788
- def find_locations(self):
789
- try:
790
- if len(self.table2.selectedItems()) == 0:
791
- show_message(
792
- fontSize=12,
793
- icon=QtWidgets.QMessageBox.Icon.Critical,
794
- title="Error",
795
- message="Please select at least 1 seed to find locations of."
796
- )
797
- return
798
-
799
- #get seeds from selected rows in table
800
- seeds = []
801
- for i in self.table2.selectionModel().selectedRows():
802
- item = self.table2.item(i.row(), 0)
803
- seeds.append(item.text())
804
-
805
- index = 0
806
- org_names = list(self.org_names.keys())
807
- #loop through each db table looking for the seed, if found, insert data in to locations table
808
- for db_file in self.db_files:
809
- conn = sqlite3.connect(db_file)
810
- c = conn.cursor()
811
- for seed in seeds:
812
- data = c.execute("SELECT chromosome, location, five, three FROM repeats WHERE seed = ? ", (seed,)).fetchone()
813
- #make sure seed was found in table, then parse and store in table
814
- if data != None:
815
- data = list(data)
816
- chroms = data[0].split(',')
817
- locs = data[1].split(',')
818
- fives = data[2].split(',')
819
- threes = data[3].split(',')
820
- if threes[0] == '':
821
- threes = []
822
- if fives[0] == '':
823
- fives = []
824
- i = 0
825
- for chrom in chroms:
826
- self.loc_finder_table.setRowCount(index + 1)
827
- seed_table = QtWidgets.QTableWidgetItem()
828
- sequence_table = QtWidgets.QTableWidgetItem()
829
- organism_table = QtWidgets.QTableWidgetItem()
830
- chromsome_table = QtWidgets.QTableWidgetItem()
831
- location_table = QtWidgets.QTableWidgetItem()
832
- seed_table.setData(QtCore.Qt.EditRole, seed)
833
- if len(fives) == 0 and len(threes) != 0:
834
- sequence_table.setData(QtCore.Qt.EditRole, seed + threes[i])
835
- elif len(threes) == 0 and len(fives) != 0:
836
- sequence_table.setData(QtCore.Qt.EditRole, fives[i] + seed)
837
- else:
838
- sequence_table.setData(QtCore.Qt.EditRole, fives[i] + seed + threes[i])
839
- organism_table.setData(QtCore.Qt.EditRole, org_names[self.db_files.index(db_file)])
840
- chromsome_table.setData(QtCore.Qt.EditRole, chrom)
841
- location_table.setData(QtCore.Qt.EditRole, abs(int(locs[i])))
842
- self.loc_finder_table.setItem(index, 0, seed_table)
843
- self.loc_finder_table.setItem(index, 1, sequence_table)
844
- self.loc_finder_table.setItem(index, 2, organism_table)
845
- self.loc_finder_table.setItem(index, 3, chromsome_table)
846
- self.loc_finder_table.setItem(index, 4, location_table)
847
- i += 1
848
- index += 1
849
-
850
- self.loc_finder_table.resizeColumnsToContents()
851
- except Exception as e:
852
- show_error("Error in find_locations() in population analysis.", e)
853
-
854
- # this function clears the loc_finder_table
855
- def clear_loc_table(self):
856
- try:
857
- self.loc_finder_table.clearContents()
858
- self.loc_finder_table.setRowCount(0)
859
- except Exception as e:
860
- show_error("Error in clear_loc_table() in population analysis.", e)
861
-
862
- # sorting function for table2 - shared seeds table: IE the table in top-right
863
- def table2_sorting(self, logicalIndex):
864
- try:
865
- self.switcher_table2[logicalIndex] *= -1
866
- if self.switcher_table2[logicalIndex] == -1:
867
- self.table2.sortItems(logicalIndex, QtCore.Qt.DescendingOrder)
868
- else:
869
- self.table2.sortItems(logicalIndex, QtCore.Qt.AscendingOrder)
870
- except Exception as e:
871
- show_error("Error in table2_sorting() in population analysis.", e)
872
-
873
- # sorting for location table: IE table in bottom right
874
- def loc_table_sorter(self, logicalIndex):
875
- try:
876
- self.switcher_loc_table[logicalIndex] *= -1
877
- if (self.switcher_loc_table[logicalIndex] == -1):
878
- self.loc_finder_table.sortItems(logicalIndex, QtCore.Qt.DescendingOrder)
879
- else:
880
- self.loc_finder_table.sortItems(logicalIndex, QtCore.Qt.AscendingOrder)
881
- except Exception as e:
882
- show_error("Error in loc_table_sorter() in population analysis.", e)
883
-
884
- #clears the table showcasing shared seeds
885
- def clear(self):
886
- try:
887
- self.table2.setRowCount(0)
888
- except Exception as e:
889
- show_error("Error in clear() in population analysis.", e)
890
-
891
- #return to main function
892
- def go_back(self):
893
- try:
894
- GlobalSettings.mainWindow.show()
895
- self.hide()
896
- except Exception as e:
897
- show_error("Error in go_back() in population analysis.", e)
898
-
899
- # this function calls the close window class. Allows the user to choose what files they want to keep/delete
900
- def closeEvent(self, event):
901
- try:
902
- GlobalSettings.mainWindow.closeFunction()
903
- event.accept()
904
- except Exception as e:
905
- show_error("Error in closeEvent() in population analysis.", e)
906
-
907
- #loading window UI class for when data is loading
908
- class loading_window(QtWidgets.QMainWindow):
909
- def __init__(self):
910
- try:
911
- super(loading_window, self).__init__()
912
- uic.loadUi(GlobalSettings.appdir + "ui/loading_data_form.ui", self)
913
- self.loading_bar.setValue(0)
914
- self.setWindowTitle("Loading Data")
915
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
916
- scale_ui(self, base_width=1920, base_height=1080, font_size=12, header_font_size=30, custom_scale_width=450, custom_scale_height=125)
917
- except Exception as e:
918
- show_error("Error initializing loading_window class in population analysis.", e)
919
-
920
- #matplotlib canvas class for the heatmap graph
921
- class MplCanvas(FigureCanvasQTAgg):
922
- def __init__(self, parent=None, width=400, height=250, dpi=100):
923
- try:
924
- fig = Figure(dpi=dpi, tight_layout=True)
925
- self.axes = fig.add_subplot(111)
926
- self.axes.clear()
927
- super(MplCanvas, self).__init__(fig)
928
- except Exception as e:
929
- show_error("Error initializing MplCanvas class in population analysis.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
controllers/scoring_window.py DELETED
@@ -1,369 +0,0 @@
1
- from utils.Algorithms import get_table_headers
2
- import models.GlobalSettings as GlobalSettings
3
- import azimuth.model_comparison as az
4
- from PyQt5 import QtWidgets, uic, QtCore
5
- import platform
6
- import traceback
7
- import math
8
- from Bio import SeqIO
9
- import numpy as np
10
- import warnings
11
- import contextlib
12
- import sys
13
-
14
- """ Code for suppressing stdout of azimuth algorithm """
15
- class DummyFile(object):
16
- def write(self, x): pass
17
-
18
- @contextlib.contextmanager
19
- def nostdout():
20
- save_stdout = sys.stdout
21
- sys.stdout = DummyFile()
22
- yield
23
- sys.stdout = save_stdout
24
-
25
- #Ignore the warnings that Azimuth spits out
26
- warnings.filterwarnings("ignore")
27
- """ ************************************************ """
28
-
29
- #global logger
30
- logger = GlobalSettings.logger
31
-
32
- # Class: scoring_window
33
- # This class opens a window for the user to select which scoring algorithm to use
34
- # Currently, the supported algorithms are:
35
- # * Azimuth 2.0, based on Rule Set 2 from Doench et al. 2016
36
- # * TBD...
37
- # Inputs:
38
- # * FASTA/FNA file that was used to create the CSPR DB that the gRNAs were generated from
39
- # - This is necessary because selected gRNAs must be found in the genomic sequence file
40
- # and algorithm-specific padding must be found for each gRNA. I.e. to get the Azimuth
41
- # score for a 23-nt gRNA+PAM sequence, 4 nt upstream of gRNA and 3 nt downstream of
42
- # PAM must be included to get a final sequence length of 30-nt (4+20+3+3).
43
- # Outputs:
44
- # * Scores for the selected gRNAs based on the selected algorithm (updated in View Targets table)
45
-
46
-
47
- class Scoring_Window(QtWidgets.QMainWindow):
48
- # init function. Sets all of the widgets/styling/buttons/variables.
49
- def __init__(self):
50
- try:
51
- # qt stuff
52
- super(Scoring_Window, self).__init__()
53
- uic.loadUi(GlobalSettings.appdir + 'ui/scoring_window.ui', self)
54
- self.progressBar.setValue(0) # Make sure the progress bar starts at 0
55
-
56
- # Button Connections
57
- self.browse_button.clicked.connect(self.fasta_browse)
58
- self.submit_button.clicked.connect(self.submit)
59
-
60
- # Initialize variables
61
- self.genome = "" # String to load in genome sequences. Key is chromosome number, value is sequence
62
- self.rev_genome = "" # String to load in reverse complement of genome sequences. Key is chromosome number, value is sequence
63
-
64
- # Styling
65
- groupbox_style = """
66
- QGroupBox:title{subcontrol-origin: margin;
67
- left: 10px;
68
- padding: 0 5px 0 5px;}
69
- QGroupBox#groupBox{border: 2px solid rgb(111,181,110);
70
- border-radius: 9px;
71
- margin-top: 10px;
72
- font: bold 14pt 'Arial';}
73
- """
74
- self.groupBox.setStyleSheet(groupbox_style)
75
- self.setWindowTitle("Select Scoring Algorithm")
76
- self.scaleUI()
77
-
78
- self.hide() # Start out hidden
79
-
80
- except Exception as e:
81
- logger.critical("Error initializing scoring_window class.")
82
- logger.critical(e)
83
- logger.critical(traceback.format_exc())
84
- msgBox = QtWidgets.QMessageBox()
85
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
86
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
87
- msgBox.setWindowTitle("Fatal Error")
88
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
89
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
90
- msgBox.exec()
91
- exit(-1)
92
-
93
- #scale UI based on current screen
94
- def scaleUI(self):
95
- try:
96
- self.repaint()
97
- QtWidgets.QApplication.processEvents()
98
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
99
- screen = QtWidgets.QApplication.screens()[screen]
100
- dpi = screen.physicalDotsPerInch()
101
- width = screen.geometry().width()
102
- height = screen.geometry().height()
103
-
104
- # font scaling
105
- fontSize = 12
106
- self.fontSize = fontSize
107
- self.centralWidget().setStyleSheet("font: " + str(fontSize) + "pt 'Arial';")
108
-
109
- self.adjustSize()
110
-
111
- currentWidth = self.size().width()
112
- currentHeight = self.size().height()
113
-
114
- # window scaling
115
- # 1920x1080 => 1150x650
116
- scaledWidth = int((width * 650) / 1920)
117
- scaledHeight = int((height * 200) / 1080)
118
-
119
- if scaledHeight < currentHeight:
120
- scaledHeight = currentHeight
121
- if scaledWidth < currentWidth:
122
- scaledWidth = currentWidth
123
-
124
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
125
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
126
- x = centerPoint.x()
127
- y = centerPoint.y()
128
- x = x - (math.ceil(scaledWidth / 2))
129
- y = y - (math.ceil(scaledHeight / 2))
130
- self.setGeometry(x, y, scaledWidth, scaledHeight)
131
-
132
- self.repaint()
133
- QtWidgets.QApplication.processEvents()
134
-
135
- except Exception as e:
136
- logger.critical("Error in scaleUI() in scoring_window.")
137
- logger.critical(e)
138
- logger.critical(traceback.format_exc())
139
- msgBox = QtWidgets.QMessageBox()
140
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
141
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
142
- msgBox.setWindowTitle("Fatal Error")
143
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
144
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
145
- msgBox.exec()
146
- exit(-1)
147
-
148
- #center UI on current screen
149
- def centerUI(self):
150
- try:
151
- self.repaint()
152
- QtWidgets.QApplication.processEvents()
153
-
154
- #center window on current screen
155
- width = self.width()
156
- height = self.height()
157
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
158
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
159
- x = centerPoint.x()
160
- y = centerPoint.y()
161
- x = x - (math.ceil(width / 2))
162
- y = y - (math.ceil(height / 2))
163
- self.setGeometry(x, y, width, height)
164
-
165
- self.repaint()
166
- QtWidgets.QApplication.processEvents()
167
- except Exception as e:
168
- logger.critical("Error in centerUI() in export to csv.")
169
- logger.critical(e)
170
- logger.critical(traceback.format_exc())
171
- msgBox = QtWidgets.QMessageBox()
172
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
173
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
174
- msgBox.setWindowTitle("Fatal Error")
175
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
176
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
177
- msgBox.exec()
178
- exit(-1)
179
-
180
- # browse for fasta function
181
- # allows user to browse for a fasta file where the full 30-nt sequence for each gRNA can be obtained
182
- def fasta_browse(self):
183
- try:
184
- filed = QtWidgets.QFileDialog() # Initialize file dialog
185
- myFile = QtWidgets.QFileDialog.getOpenFileName(filed, "Choose a File")
186
- if (myFile[0] != ""): # Make sure file is not empty
187
- if not myFile[0].endswith(".fa") and not myFile[0].endswith(".fna") and not myFile[0].endswith(".fasta"): # Make sure file the correct type
188
- msgBox = QtWidgets.QMessageBox()
189
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
190
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
191
- msgBox.setWindowTitle("File Selection Error")
192
- msgBox.setText("You have selected an incorrect type of file. Please choose a FASTA/FNA file.")
193
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
194
- msgBox.exec()
195
- return
196
- else:
197
- self.file = myFile[0]
198
- self.fasta_edit.setText(str(myFile[0]))
199
-
200
- except Exception as e:
201
- logger.critical("Error in fasta_browse() in scoring_window.")
202
- logger.critical(e)
203
- logger.critical(traceback.format_exc())
204
- msgBox = QtWidgets.QMessageBox()
205
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
206
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
207
- msgBox.setWindowTitle("Fatal Error")
208
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
209
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
210
- msgBox.exec()
211
- exit(-1)
212
-
213
- # This function loads in the selcted fasta/fna file's sequences so that they can be checked for gRNA sequences
214
- def load_fasta(self):
215
- try:
216
- if self.fasta_edit.text() == "": # If no file has been selected, throw an error and let user try again
217
- msgBox = QtWidgets.QMessageBox()
218
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
219
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
220
- msgBox.setWindowTitle("Error")
221
- msgBox.setText("No file has been selected. Please select a FASTA/FNA file.")
222
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
223
- msgBox.exec()
224
- else:
225
- self.progressBar.setValue(10) # Update progress bar
226
- # Get the current chromosome to avoid having to load in the entire FASTA file to memory
227
- current_chrom = int(GlobalSettings.mainWindow.Results.featureDict[GlobalSettings.mainWindow.Results.comboBoxGene.currentText()][0])
228
- ### Save the chromosome of interest and its reverse complement to the strings self.genome and self.rev_genome, respectively.
229
- for i, record in enumerate(SeqIO.parse(self.fasta_edit.text(), "fasta")):
230
- if i+1 == current_chrom: # Only save chromosome that contains the selected gRNAs
231
- self.genome = record.seq.__str__().upper()
232
- self.rev_genome = record.seq.reverse_complement().__str__().upper()
233
- else:
234
- continue
235
- self.progressBar.setValue(30) # Update progress bar
236
-
237
- except Exception as e:
238
- logger.critical("Error loading in fasta file in scoring_window.")
239
- logger.critical(e)
240
- logger.critical(traceback.format_exc())
241
- msgBox = QtWidgets.QMessageBox()
242
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
243
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
244
- msgBox.setWindowTitle("Fatal Error")
245
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
246
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
247
- msgBox.exec()
248
- exit(-1)
249
- # This function searches for each selected gRNA in the FASTA file provided and if it is found, scores it according to the selected algorithm.
250
- # gRNAs that cannot be found are scored as -1's and reported to the user.
251
- def score_azimuth(self):
252
- try:
253
- ### Intialize the data structures for storing results
254
- guide_list = []
255
- reject_list = []
256
- full_seqs = []
257
-
258
- ### Find the full sequences for each gRNA from within the FASTA file and save them to full_seqs. Save index of sequences that could not be found.
259
- targettable = GlobalSettings.mainWindow.Results.targetTable # Make new variable for table name so that referencing isn't quite so tedious
260
- it = 0 # Initialize iterator
261
-
262
- self.progressBar.setValue(50) # Update progress bar
263
- scale = 20/len(targettable.selectionModel().selectedRows()) # Scale the next 20% of the progressBar to be completed over all the gRNAs
264
-
265
- for i in range(targettable.rowCount()):
266
- if targettable.item(i, 0).isSelected(): # If row was selected...
267
- strand = targettable.item(i, 3).text() # Grab strand
268
- seq = targettable.item(i, 2).text() + targettable.item(i,4).text() # Grab full seq (guide+PAM)
269
- guide_list.append(seq) # Save the gRNA to guide_list
270
- if strand == "+":
271
- tmp = self.genome.find(seq) # Search forward strand of genome for gRNA
272
- if tmp != -1: # If sequence was found
273
- full_seqs.append(self.genome[tmp-4:tmp+26]) # Get full 30-nt sequence and append to full_seqsa
274
- else: # If sequence was not found
275
- reject_list.append(it) # Append index of gRNA to reject_list
276
- else: # If strand == "-"
277
- tmp = self.rev_genome.find(seq) # Search reverse strand of genome for gRNA
278
- if tmp != -1: # If sequence was found
279
- full_seqs.append(self.rev_genome[tmp-4:tmp+26]) # Get full 30-net sequence and append to pass list
280
- else:
281
- reject_list.append(it) # Append index of gRNA to reject_list
282
- increment = scale*(it+1) # Calculate progressBar increment for 1 gRNA search
283
- self.progressBar.setValue(int(self.progressBar.value()+increment)) # Update progress bar
284
- it += 1 # Iterate iterator
285
- else: # If row in table wasn't selected, skip it
286
- continue
287
-
288
- if len(full_seqs) != 0: # If some sequences were found...
289
- full_seqs = np.array(full_seqs) # Convert 30-nt seqs into a np.array
290
- with nostdout(): # Silence Azimuth's print statements
291
- az_scores = az.predict(full_seqs)*100 # Predict scores and multiply by 100 (a la CHOP-CHOP)
292
- if len(reject_list) > 0: # If some sequences were not found
293
- msg_string = "\n".join([guide_list[i] for i in reject_list]) # Separate missing sequences by newline char
294
- ### Insert -1's for each guide that wasn't found
295
- for i in reject_list:
296
- az_scores = np.insert(az_scores, i, -1)
297
- ### Generate a message showing the sequences that weren't found
298
- msgBox = QtWidgets.QMessageBox()
299
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
300
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Information)
301
- msgBox.setWindowTitle("Some Sequences Not Found!")
302
- msgBox.setText("The following sequences (gRNA+PAM) were not found:\n%s\n\nThey have been given placeholder scores of -1." % msg_string)
303
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
304
- msgBox.exec()
305
- else: # If no sequences were found...
306
- msgBox = QtWidgets.QMessageBox()
307
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
308
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Information)
309
- msgBox.setWindowTitle("No Sequences Found!")
310
- msgBox.setText("None of the selected guides were found. Please ensure you have the correct FASTA file and try again.")
311
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
312
- msgBox.exec()
313
- return
314
-
315
- self.progressBar.setValue(80) # Update progress bar
316
- self.transfer_results(az_scores, "Azimuth 2.0") # Call transfer_results to fill the table with the scores
317
-
318
- except Exception as e:
319
- logger.critical("Error in score_azimuth() in scoring_window.")
320
- logger.critical(e)
321
- logger.critical(traceback.format_exc())
322
- msgBox = QtWidgets.QMessageBox()
323
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
324
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
325
- msgBox.setWindowTitle("Fatal Error")
326
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
327
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
328
- msgBox.exec()
329
- exit(-1)
330
-
331
- # This function searches for each selected gRNA in the FASTA file provided and if it is found, scores it according to the selected algorithm.
332
- # The table in View Targets is then updated to include the fresh scores. gRNAs that cannot be found are reported as -1's.
333
- def transfer_results(self, scores, algorithm):
334
- targettable = GlobalSettings.mainWindow.Results.targetTable # Make new variable for table name so that referencing isn't quite so tedious
335
- scale = 20/len(targettable.selectionModel().selectedRows()) # Scale the next 20% of progressBar to be completed over all the gRNAs
336
- headers = get_table_headers(targettable) # Get table headers
337
- num_cols = len(headers) # Get number of columns
338
- if algorithm not in headers: # If this algorithm hasn't been ran yet, add a column for it and place scores in it.
339
- targettable.insertColumn(num_cols-2) # Add column before off-target columns
340
- targettable.setHorizontalHeaderLabels(["Location", "Endonuclease", "Sequence", "Strand", "PAM", "Score", algorithm, "Off-Target", "Details"]) # Update column headers
341
- targettable.horizontalHeader().setSectionResizeMode(num_cols, QtWidgets.QHeaderView.Stretch) #Ensures last column goes to the edge of table
342
-
343
- col_index = get_table_headers(targettable).index(algorithm) # Get index of column to add scores to
344
- ### Add scores to algorithm column
345
- it = 0
346
- for i in range(targettable.rowCount()):
347
- if targettable.item(i, 0).isSelected(): # If row was selected, add the corresponding score to the table
348
- score = QtWidgets.QTableWidgetItem() # Create new table item for the score to be placed into
349
- score.setData(QtCore.Qt.EditRole, round(float(scores[it]),2))
350
- targettable.setItem(i,col_index, score) # Add the item
351
- targettable.item(i,col_index).setSelected(True) # Make it selected by default to prevent export issues
352
- ## Update progress
353
- increment = scale*(it+1)
354
- self.progressBar.setValue(int(self.progressBar.value()+increment)) # Update progress bar
355
- it += 1
356
-
357
-
358
- targettable.resizeColumnsToContents()
359
- self.progressBar.setValue(100)
360
- self.close_window()
361
-
362
- def close_window(self):
363
- self.progressBar.setValue(0) # Reset progress bar
364
- self.hide()
365
-
366
- def submit(self):
367
- self.progressBar.setValue(0)
368
- self.load_fasta()
369
- self.score_azimuth()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/mac.spec → mac.spec RENAMED
@@ -1,35 +1,34 @@
1
  # -*- mode: python ; coding: utf-8 -*-
2
- import sys
3
- sys.setrecursionlimit(5000)
4
  block_cipher = None
5
 
6
 
7
  a = Analysis(['main.py'],
8
- pathex=['/Users/ddooley/bioinformatics_packages/individual_packages/crispr_tools/CASPERapp'],
9
  datas=[
10
  ('OffTargetFolder', 'OffTargetFolder'),
11
  ('SeqFinderFolder', 'SeqFinderFolder'),
12
- ('*.ui','.'),
 
 
 
 
13
  ('CASPERinfo', '.'),
14
- ('CASPER-logo.jpg', '.'),
15
- ('CASPER_icon.icns', '.'),
16
  ('genomeBrowserTemplate.html', '.'),
17
- ('/Users/ddooley/venvs/casper_env/lib/python3.8/site-packages/azimuth','azimuth')
18
  ],
19
  hiddenimports=[],
20
  hookspath=[],
21
  runtime_hooks=[],
22
- excludes=[
23
- 'cryptography',
24
- 'Crypto',
25
- 'tkinter'
26
- ],
27
  win_no_prefer_redirects=False,
28
  win_private_assemblies=False,
29
  cipher=block_cipher,
30
  noarchive=False)
 
31
  pyz = PYZ(a.pure, a.zipped_data,
32
  cipher=block_cipher)
 
33
  exe = EXE(pyz,
34
  a.scripts,
35
  [],
@@ -39,7 +38,13 @@ exe = EXE(pyz,
39
  bootloader_ignore_signals=False,
40
  strip=False,
41
  upx=True,
42
- console=False)
 
 
 
 
 
 
43
  coll = COLLECT(exe,
44
  a.binaries,
45
  a.zipfiles,
@@ -49,7 +54,8 @@ coll = COLLECT(exe,
49
  upx_exclude=[],
50
  name='CASPERapp')
51
 
52
- app = BUNDLE(coll, icon='CASPER_icon.icns',
53
  name='CASPERapp.app',
 
54
  version='2.0.1',
55
  bundle_identifier=None)
 
1
  # -*- mode: python ; coding: utf-8 -*-
 
 
2
  block_cipher = None
3
 
4
 
5
  a = Analysis(['main.py'],
6
+ pathex=[],
7
  datas=[
8
  ('OffTargetFolder', 'OffTargetFolder'),
9
  ('SeqFinderFolder', 'SeqFinderFolder'),
10
+ ('controllers', 'controllers'),
11
+ ('models', 'models'),
12
+ ('utils', 'utils'),
13
+ ('views', 'views'),
14
+ ('ui', 'ui'),
15
  ('CASPERinfo', '.'),
16
+ ('assets', 'assets'),
 
17
  ('genomeBrowserTemplate.html', '.'),
18
+ ('logs', 'logs')
19
  ],
20
  hiddenimports=[],
21
  hookspath=[],
22
  runtime_hooks=[],
23
+ excludes=[],
 
 
 
 
24
  win_no_prefer_redirects=False,
25
  win_private_assemblies=False,
26
  cipher=block_cipher,
27
  noarchive=False)
28
+
29
  pyz = PYZ(a.pure, a.zipped_data,
30
  cipher=block_cipher)
31
+
32
  exe = EXE(pyz,
33
  a.scripts,
34
  [],
 
38
  bootloader_ignore_signals=False,
39
  strip=False,
40
  upx=True,
41
+ console=False,
42
+ disable_windowed_traceback=False,
43
+ target_arch=None,
44
+ codesign_identity=None,
45
+ entitlements_file=None,
46
+ icon='assets/CASPER_icon.icns')
47
+
48
  coll = COLLECT(exe,
49
  a.binaries,
50
  a.zipfiles,
 
54
  upx_exclude=[],
55
  name='CASPERapp')
56
 
57
+ app = BUNDLE(coll,
58
  name='CASPERapp.app',
59
+ icon='assets/CASPER_icon.icns',
60
  version='2.0.1',
61
  bundle_identifier=None)
main.py DELETED
@@ -1,91 +0,0 @@
1
- import sys
2
- import os
3
- from PyQt5 import QtWidgets, Qt, QtGui, QtCore, uic
4
- import models.GlobalSettings as GlobalSettings
5
- import controllers.multitargeting as multitargeting
6
- import controllers.populationAnalysis as populationAnalysis
7
- import platform
8
- import logging
9
- from utils.ui import show_error, center_ui
10
- from views.annotation_functions import *
11
- from views.StartupWindow import StartupWindow
12
- from views.CMainWindow import CMainWindow
13
-
14
- logger = GlobalSettings.logger
15
-
16
- fontSize = 12
17
-
18
- def setup_logger():
19
- logger.info(f"System OS: {platform.system()}")
20
-
21
- if hasattr(sys, 'frozen'):
22
- logger.info("Running a packaged version of CASPER.")
23
- GlobalSettings.appdir = sys.executable
24
- if platform.system() == 'Windows':
25
- GlobalSettings.appdir = sys._MEIPASS + "\\"
26
- else:
27
- GlobalSettings.appdir = GlobalSettings.appdir[:GlobalSettings.appdir.rfind("Contents/") + 9] + "Resources/"
28
-
29
- else:
30
- logger.info("Running a non-packaged version of CASPER.")
31
- GlobalSettings.appdir = os.path.dirname(os.path.abspath(__file__)) + ('\\' if platform.system() == 'Windows' else '/')
32
-
33
- fh = logging.FileHandler(GlobalSettings.appdir + 'logs/app.log', mode='w')
34
- fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
35
- fh.setFormatter(fh_formatter)
36
- fh.setLevel(logging.DEBUG)
37
- GlobalSettings.logger.addHandler(fh)
38
-
39
- # def update_directory(current_directory, fontSize, update_ui_callback):
40
- # try:
41
- # filed = QtWidgets.QFileDialog()
42
- # new_directory = QtWidgets.QFileDialog.getExistingDirectory(
43
- # filed, "Open a folder...", current_directory, QtWidgets.QFileDialog.ShowDirsOnly)
44
-
45
- # if not os.path.isdir(new_directory):
46
- # show_message("Not a directory", "The directory you selected does not exist.", fontSize)
47
- # return
48
-
49
- # if not any(file.endswith(".cspr") for file in os.listdir(new_directory)):
50
- # show_message("Directory is invalid!", "You must select a directory with CSPR Files!", fontSize)
51
- # return
52
-
53
- # if platform.system() == "Windows":
54
- # new_directory = new_directory.replace("/", "\\")
55
-
56
- # os.chdir(new_directory)
57
- # GlobalSettings.CSPR_DB = new_directory
58
- # update_ui_callback(new_directory)
59
-
60
- # except Exception as e:
61
- # show_critical_error("Error in updating directory", e, fontSize)
62
-
63
- def main():
64
- setup_logger()
65
- app = QtWidgets.QApplication(sys.argv)
66
- app.setOrganizationName("TrinhLab-UTK")
67
- app.setApplicationName("CASPER")
68
-
69
- #load startup window
70
- try:
71
- # Initialize windows
72
- startup = StartupWindow()
73
- logger.debug("Successfully initialized Startup Window.")
74
-
75
- GlobalSettings.mainWindow = CMainWindow(os.getcwd())
76
- logger.debug("Successfully initialized Main Window.")
77
-
78
- GlobalSettings.MTWin = multitargeting.Multitargeting()
79
- logger.debug("Successfully initialized Multi-targeting Window.")
80
-
81
- GlobalSettings.pop_Analysis = populationAnalysis.Pop_Analysis()
82
- logger.debug("Successfully initialized Population Analysis Window.")
83
-
84
- center_ui(startup)
85
- startup.show()
86
- sys.exit(app.exec_())
87
- except Exception as e:
88
- show_error("An error occurred during application initialization", e)
89
-
90
- if __name__ == '__main__':
91
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
models/CSPRparser.py DELETED
@@ -1,115 +0,0 @@
1
- from utils.Algorithms import SeqTranslate
2
- import gzip
3
-
4
- ##################################################################################################################################
5
- # Use: Use as a parser for the cspr files
6
- # Precondition: Only to the used with .cspr files. Will not work with any other files
7
- # This class also took some of the parsing functions from with classes (Multitargeting and Results) and stores them in here
8
- ##################################################################################################################################
9
-
10
- class CSPRparser:
11
- def __init__(self, inputFileName):
12
- self.multiSum = 0 # multitargetting sum taken from the previous version of make_graphs
13
- self.multiCount = 0 # multitargetting count taken from the previous version of make_graphs
14
- self.seqTrans = SeqTranslate() # SeqTranslate variable. for decrompressing the data
15
- self.chromesomeList = list() # list of a list for the chromesomes. As it currently stands, this variable is used in both read_chromesomes and in read_targets
16
- self.karystatsList = list() # list of (ints) of the karyStats (whatever those are) to be used for the get_chrom_length function
17
- self.genome = "" # genome name
18
- self.misc = "" # anything from the misc line
19
- self.repeats = {} # dictionary of the number of repeats. See the read_repeats function for more info
20
- self.seeds = {} # dictionary of which chromesomes are repeats. See the read_repeats function for more info
21
- self.dec_tup_data = {}
22
- self.chromesomesSelectedList = list()
23
- # data for population analysis
24
- # dict:
25
- # key = the seed
26
- # value = tuple (org name, chom #, location, sequence, pam, score, strand, endo)
27
- self.popData = {}
28
-
29
- # file path variable
30
- self.fileName = inputFileName
31
-
32
- def gen_lib_parser(self, genDict, endo):
33
- retDict = dict()
34
- for gene in genDict:
35
- retDict[gene] = list()
36
- retDict[gene] = self.read_targets('', (genDict[gene][0], genDict[gene][1], genDict[gene][2]), endo)
37
- return retDict
38
-
39
- def read_first_lines(self):
40
- with open(self.fileName, 'r') as f:
41
- i = 0
42
- for line in f:
43
- if i > 2:
44
- break
45
- else:
46
- line = str(line)
47
- if i == 0:
48
- colonIndex = line.find(':') + 2
49
- buffer1 = line[colonIndex:]
50
- self.genome = buffer1
51
- elif i == 1:
52
- colonIndex = line.find(':') + 2
53
- k_data = line[colonIndex:]
54
- k_data = k_data.split(',')
55
- k_data = k_data[:-1]
56
- for k in k_data:
57
- self.karystatsList.append(int(k))
58
- else:
59
- colonIndex = line.find(':') + 2
60
- buffer1 = line[colonIndex:]
61
- self.misc = buffer1
62
- i += 1
63
-
64
- def get_chromesome_names(self):
65
- self.chromesomesSelectedList.clear()
66
- with open(self.fileName,'r') as f:
67
- i = 0
68
- for line in f:
69
- line = str(line)
70
- if line == 'REPEATS':
71
- break
72
- elif '>' in line:
73
- self.chromesomesSelectedList.append(line)
74
- if i == 0:
75
- retGen = line
76
- elif i == 2:
77
- retMisc = line
78
- i += 1
79
- return retGen, retMisc
80
-
81
- def read_targets(self, genename, pos_tuple, endo):
82
- i = 0
83
- retList = []
84
- header = False
85
- with open(self.fileName, 'r') as f:
86
- for line in f:
87
- line = str(line).strip()
88
- if i > 2:
89
- if '>' in line and '(' + str(pos_tuple[0]) + ')' in line:
90
- header = True
91
- elif header == True:
92
-
93
- if line.find('>') != -1:
94
- break
95
- line = line.split(',')
96
- if abs(int(line[0])) >= int(pos_tuple[1]) and abs(int(line[0])) < int(pos_tuple[2]):
97
- if int(line[0]) < 0:
98
- strand = "-"
99
- else:
100
- strand = "+"
101
- retList.append((line[0], line[1], line[2], line[3], strand, endo))
102
- elif int(line[0]) >= int(pos_tuple[2]):
103
- break
104
- elif line == 'REPEATS':
105
- break
106
- i += 1
107
- return retList
108
-
109
- def uniq_seq_count(self):
110
- self.unique_targets = 0
111
- for chromo in self.chromesomeList:
112
- for data in chromo:
113
- if len(data) == 6:
114
- self.unique_targets += 1
115
- return self.unique_targets
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
models/GlobalSettings.py DELETED
@@ -1,15 +0,0 @@
1
- import logging
2
-
3
- """File stores all global variables, mainly used for file information/directory monitoring"""
4
-
5
- # setup logger in global space
6
- logger = logging.getLogger(__name__)
7
- logger.setLevel(logging.DEBUG)
8
-
9
- OPERATING_SYSTEM_ID = ""
10
-
11
- CSPR_DB = ""
12
-
13
- appdir = ""
14
-
15
- algorithms = ["Azimuth 2.0"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/CASPER_main.ui DELETED
@@ -1,1262 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="enabled">
6
- <bool>true</bool>
7
- </property>
8
- <property name="geometry">
9
- <rect>
10
- <x>0</x>
11
- <y>0</y>
12
- <width>1021</width>
13
- <height>777</height>
14
- </rect>
15
- </property>
16
- <property name="font">
17
- <font>
18
- <family>Arial</family>
19
- <pointsize>12</pointsize>
20
- <weight>50</weight>
21
- <italic>false</italic>
22
- <bold>false</bold>
23
- </font>
24
- </property>
25
- <property name="windowTitle">
26
- <string>CASPER</string>
27
- </property>
28
- <property name="styleSheet">
29
- <string notr="true"/>
30
- </property>
31
- <widget class="QWidget" name="centralwidget">
32
- <property name="font">
33
- <font>
34
- <family>Arial</family>
35
- <pointsize>12</pointsize>
36
- <weight>50</weight>
37
- <italic>false</italic>
38
- <bold>false</bold>
39
- </font>
40
- </property>
41
- <property name="styleSheet">
42
- <string notr="true"/>
43
- </property>
44
- <layout class="QGridLayout" name="gridLayout_6">
45
- <item row="1" column="3">
46
- <widget class="QLabel" name="label_5">
47
- <property name="minimumSize">
48
- <size>
49
- <width>50</width>
50
- <height>0</height>
51
- </size>
52
- </property>
53
- <property name="maximumSize">
54
- <size>
55
- <width>50</width>
56
- <height>16777215</height>
57
- </size>
58
- </property>
59
- <property name="text">
60
- <string/>
61
- </property>
62
- </widget>
63
- </item>
64
- <item row="0" column="1" colspan="2">
65
- <spacer name="verticalSpacer">
66
- <property name="orientation">
67
- <enum>Qt::Vertical</enum>
68
- </property>
69
- <property name="sizeType">
70
- <enum>QSizePolicy::Fixed</enum>
71
- </property>
72
- <property name="sizeHint" stdset="0">
73
- <size>
74
- <width>20</width>
75
- <height>20</height>
76
- </size>
77
- </property>
78
- </spacer>
79
- </item>
80
- <item row="5" column="0" rowspan="2">
81
- <spacer name="horizontalSpacer">
82
- <property name="orientation">
83
- <enum>Qt::Horizontal</enum>
84
- </property>
85
- <property name="sizeType">
86
- <enum>QSizePolicy::Fixed</enum>
87
- </property>
88
- <property name="sizeHint" stdset="0">
89
- <size>
90
- <width>20</width>
91
- <height>20</height>
92
- </size>
93
- </property>
94
- </spacer>
95
- </item>
96
- <item row="1" column="1">
97
- <widget class="QLabel" name="label_8">
98
- <property name="sizePolicy">
99
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
100
- <horstretch>0</horstretch>
101
- <verstretch>0</verstretch>
102
- </sizepolicy>
103
- </property>
104
- <property name="minimumSize">
105
- <size>
106
- <width>0</width>
107
- <height>0</height>
108
- </size>
109
- </property>
110
- <property name="maximumSize">
111
- <size>
112
- <width>16777215</width>
113
- <height>16777215</height>
114
- </size>
115
- </property>
116
- <property name="font">
117
- <font>
118
- <family>Arial</family>
119
- <pointsize>12</pointsize>
120
- <weight>75</weight>
121
- <italic>false</italic>
122
- <bold>true</bold>
123
- </font>
124
- </property>
125
- <property name="styleSheet">
126
- <string notr="true"/>
127
- </property>
128
- <property name="text">
129
- <string>CASPER</string>
130
- </property>
131
- </widget>
132
- </item>
133
- <item row="1" column="2" alignment="Qt::AlignRight">
134
- <widget class="QLabel" name="label_7">
135
- <property name="sizePolicy">
136
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
137
- <horstretch>0</horstretch>
138
- <verstretch>0</verstretch>
139
- </sizepolicy>
140
- </property>
141
- <property name="minimumSize">
142
- <size>
143
- <width>0</width>
144
- <height>0</height>
145
- </size>
146
- </property>
147
- <property name="maximumSize">
148
- <size>
149
- <width>16777215</width>
150
- <height>16777215</height>
151
- </size>
152
- </property>
153
- <property name="font">
154
- <font>
155
- <family>Arial</family>
156
- <pointsize>12</pointsize>
157
- <weight>50</weight>
158
- <italic>false</italic>
159
- <bold>false</bold>
160
- </font>
161
- </property>
162
- <property name="styleSheet">
163
- <string notr="true"/>
164
- </property>
165
- <property name="text">
166
- <string>V2.0 (Beta) CRISPR Associated Software for Pathway Engineering and Research</string>
167
- </property>
168
- </widget>
169
- </item>
170
- <item row="2" column="1" colspan="2">
171
- <widget class="Line" name="line">
172
- <property name="sizePolicy">
173
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
174
- <horstretch>0</horstretch>
175
- <verstretch>0</verstretch>
176
- </sizepolicy>
177
- </property>
178
- <property name="maximumSize">
179
- <size>
180
- <width>1000000</width>
181
- <height>16777215</height>
182
- </size>
183
- </property>
184
- <property name="styleSheet">
185
- <string notr="true">color: rgb(0, 0, 0);</string>
186
- </property>
187
- <property name="lineWidth">
188
- <number>2</number>
189
- </property>
190
- <property name="midLineWidth">
191
- <number>1</number>
192
- </property>
193
- <property name="orientation">
194
- <enum>Qt::Horizontal</enum>
195
- </property>
196
- </widget>
197
- </item>
198
- <item row="5" column="1" rowspan="2" colspan="2">
199
- <layout class="QGridLayout" name="gridLayout_7">
200
- <property name="sizeConstraint">
201
- <enum>QLayout::SetDefaultConstraint</enum>
202
- </property>
203
- <item row="0" column="0" rowspan="2">
204
- <widget class="QGroupBox" name="Step1">
205
- <property name="sizePolicy">
206
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
207
- <horstretch>0</horstretch>
208
- <verstretch>0</verstretch>
209
- </sizepolicy>
210
- </property>
211
- <property name="minimumSize">
212
- <size>
213
- <width>0</width>
214
- <height>0</height>
215
- </size>
216
- </property>
217
- <property name="maximumSize">
218
- <size>
219
- <width>16777215</width>
220
- <height>16777215</height>
221
- </size>
222
- </property>
223
- <property name="font">
224
- <font>
225
- <family>Arial</family>
226
- <pointsize>12</pointsize>
227
- <weight>50</weight>
228
- <italic>false</italic>
229
- <bold>false</bold>
230
- </font>
231
- </property>
232
- <property name="styleSheet">
233
- <string notr="true"/>
234
- </property>
235
- <property name="title">
236
- <string>Step 1: Select Organism and Endonuclease</string>
237
- </property>
238
- <layout class="QGridLayout" name="gridLayout">
239
- <item row="3" column="2">
240
- <widget class="QComboBox" name="endoChoice">
241
- <property name="sizePolicy">
242
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
243
- <horstretch>0</horstretch>
244
- <verstretch>0</verstretch>
245
- </sizepolicy>
246
- </property>
247
- <property name="minimumSize">
248
- <size>
249
- <width>0</width>
250
- <height>0</height>
251
- </size>
252
- </property>
253
- <property name="maximumSize">
254
- <size>
255
- <width>16777215</width>
256
- <height>16777215</height>
257
- </size>
258
- </property>
259
- <property name="font">
260
- <font>
261
- <family>Arial</family>
262
- <pointsize>8</pointsize>
263
- <weight>50</weight>
264
- <italic>false</italic>
265
- <bold>false</bold>
266
- </font>
267
- </property>
268
- </widget>
269
- </item>
270
- <item row="2" column="2">
271
- <widget class="QComboBox" name="orgChoice">
272
- <property name="enabled">
273
- <bool>true</bool>
274
- </property>
275
- <property name="sizePolicy">
276
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
277
- <horstretch>0</horstretch>
278
- <verstretch>0</verstretch>
279
- </sizepolicy>
280
- </property>
281
- <property name="minimumSize">
282
- <size>
283
- <width>0</width>
284
- <height>0</height>
285
- </size>
286
- </property>
287
- <property name="maximumSize">
288
- <size>
289
- <width>16777215</width>
290
- <height>16777215</height>
291
- </size>
292
- </property>
293
- <property name="font">
294
- <font>
295
- <family>Arial</family>
296
- <pointsize>8</pointsize>
297
- <weight>50</weight>
298
- <italic>false</italic>
299
- <bold>false</bold>
300
- </font>
301
- </property>
302
- </widget>
303
- </item>
304
- <item row="2" column="0">
305
- <widget class="QLabel" name="label_2">
306
- <property name="sizePolicy">
307
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
308
- <horstretch>0</horstretch>
309
- <verstretch>0</verstretch>
310
- </sizepolicy>
311
- </property>
312
- <property name="minimumSize">
313
- <size>
314
- <width>0</width>
315
- <height>0</height>
316
- </size>
317
- </property>
318
- <property name="maximumSize">
319
- <size>
320
- <width>16777215</width>
321
- <height>16777215</height>
322
- </size>
323
- </property>
324
- <property name="font">
325
- <font>
326
- <family>Arial</family>
327
- <pointsize>12</pointsize>
328
- <weight>50</weight>
329
- <italic>false</italic>
330
- <bold>false</bold>
331
- </font>
332
- </property>
333
- <property name="styleSheet">
334
- <string notr="true"/>
335
- </property>
336
- <property name="text">
337
- <string>Organism:</string>
338
- </property>
339
- </widget>
340
- </item>
341
- <item row="1" column="0" colspan="3">
342
- <spacer name="verticalSpacer_7">
343
- <property name="orientation">
344
- <enum>Qt::Vertical</enum>
345
- </property>
346
- <property name="sizeType">
347
- <enum>QSizePolicy::Fixed</enum>
348
- </property>
349
- <property name="sizeHint" stdset="0">
350
- <size>
351
- <width>10</width>
352
- <height>10</height>
353
- </size>
354
- </property>
355
- </spacer>
356
- </item>
357
- <item row="5" column="0" colspan="3">
358
- <spacer name="verticalSpacer_8">
359
- <property name="orientation">
360
- <enum>Qt::Vertical</enum>
361
- </property>
362
- <property name="sizeType">
363
- <enum>QSizePolicy::Fixed</enum>
364
- </property>
365
- <property name="sizeHint" stdset="0">
366
- <size>
367
- <width>10</width>
368
- <height>10</height>
369
- </size>
370
- </property>
371
- </spacer>
372
- </item>
373
- <item row="3" column="0">
374
- <widget class="QLabel" name="label">
375
- <property name="sizePolicy">
376
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
377
- <horstretch>0</horstretch>
378
- <verstretch>0</verstretch>
379
- </sizepolicy>
380
- </property>
381
- <property name="minimumSize">
382
- <size>
383
- <width>0</width>
384
- <height>0</height>
385
- </size>
386
- </property>
387
- <property name="maximumSize">
388
- <size>
389
- <width>16777215</width>
390
- <height>16777215</height>
391
- </size>
392
- </property>
393
- <property name="font">
394
- <font>
395
- <family>Arial</family>
396
- <pointsize>12</pointsize>
397
- <weight>50</weight>
398
- <italic>false</italic>
399
- <bold>false</bold>
400
- </font>
401
- </property>
402
- <property name="styleSheet">
403
- <string notr="true"/>
404
- </property>
405
- <property name="text">
406
- <string>Endonuclease:</string>
407
- </property>
408
- </widget>
409
- </item>
410
- </layout>
411
- </widget>
412
- </item>
413
- <item row="2" column="0" rowspan="2">
414
- <widget class="QGroupBox" name="Step2">
415
- <property name="sizePolicy">
416
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
417
- <horstretch>0</horstretch>
418
- <verstretch>0</verstretch>
419
- </sizepolicy>
420
- </property>
421
- <property name="minimumSize">
422
- <size>
423
- <width>0</width>
424
- <height>0</height>
425
- </size>
426
- </property>
427
- <property name="maximumSize">
428
- <size>
429
- <width>16777215</width>
430
- <height>16777215</height>
431
- </size>
432
- </property>
433
- <property name="font">
434
- <font>
435
- <family>Arial</family>
436
- <pointsize>12</pointsize>
437
- <weight>50</weight>
438
- <italic>false</italic>
439
- <bold>false</bold>
440
- </font>
441
- </property>
442
- <property name="styleSheet">
443
- <string notr="true"/>
444
- </property>
445
- <property name="title">
446
- <string>Step 2: Choose Annotation File</string>
447
- </property>
448
- <layout class="QGridLayout" name="gridLayout_5">
449
- <property name="topMargin">
450
- <number>15</number>
451
- </property>
452
- <item row="2" column="1" colspan="2">
453
- <widget class="QLabel" name="label_4">
454
- <property name="sizePolicy">
455
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
456
- <horstretch>0</horstretch>
457
- <verstretch>0</verstretch>
458
- </sizepolicy>
459
- </property>
460
- <property name="maximumSize">
461
- <size>
462
- <width>16777215</width>
463
- <height>16777215</height>
464
- </size>
465
- </property>
466
- <property name="font">
467
- <font>
468
- <family>Arial</family>
469
- <pointsize>12</pointsize>
470
- <weight>50</weight>
471
- <italic>false</italic>
472
- <bold>false</bold>
473
- </font>
474
- </property>
475
- <property name="styleSheet">
476
- <string notr="true"/>
477
- </property>
478
- <property name="text">
479
- <string>Select local file or download from NCBI:</string>
480
- </property>
481
- <property name="alignment">
482
- <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
483
- </property>
484
- </widget>
485
- </item>
486
- <item row="4" column="1" colspan="2">
487
- <widget class="QLabel" name="label_3">
488
- <property name="sizePolicy">
489
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
490
- <horstretch>0</horstretch>
491
- <verstretch>0</verstretch>
492
- </sizepolicy>
493
- </property>
494
- <property name="minimumSize">
495
- <size>
496
- <width>0</width>
497
- <height>0</height>
498
- </size>
499
- </property>
500
- <property name="maximumSize">
501
- <size>
502
- <width>16777215</width>
503
- <height>16777215</height>
504
- </size>
505
- </property>
506
- <property name="font">
507
- <font>
508
- <family>Arial</family>
509
- <pointsize>12</pointsize>
510
- <weight>50</weight>
511
- <italic>false</italic>
512
- <bold>false</bold>
513
- </font>
514
- </property>
515
- <property name="text">
516
- <string>Local Annotation Files:</string>
517
- </property>
518
- <property name="alignment">
519
- <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
520
- </property>
521
- </widget>
522
- </item>
523
- <item row="5" column="1" colspan="2">
524
- <widget class="QComboBox" name="annotation_files">
525
- <property name="sizePolicy">
526
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
527
- <horstretch>0</horstretch>
528
- <verstretch>0</verstretch>
529
- </sizepolicy>
530
- </property>
531
- <property name="minimumSize">
532
- <size>
533
- <width>0</width>
534
- <height>0</height>
535
- </size>
536
- </property>
537
- <property name="maximumSize">
538
- <size>
539
- <width>16777215</width>
540
- <height>16777215</height>
541
- </size>
542
- </property>
543
- <property name="font">
544
- <font>
545
- <family>Arial</family>
546
- <pointsize>12</pointsize>
547
- <weight>50</weight>
548
- <italic>false</italic>
549
- <bold>false</bold>
550
- </font>
551
- </property>
552
- </widget>
553
- </item>
554
- <item row="6" column="1" colspan="2">
555
- <spacer name="verticalSpacer_6">
556
- <property name="orientation">
557
- <enum>Qt::Vertical</enum>
558
- </property>
559
- <property name="sizeType">
560
- <enum>QSizePolicy::Fixed</enum>
561
- </property>
562
- <property name="sizeHint" stdset="0">
563
- <size>
564
- <width>10</width>
565
- <height>10</height>
566
- </size>
567
- </property>
568
- </spacer>
569
- </item>
570
- <item row="3" column="1" colspan="2">
571
- <widget class="QPushButton" name="launch_ncbi_button">
572
- <property name="sizePolicy">
573
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
574
- <horstretch>0</horstretch>
575
- <verstretch>0</verstretch>
576
- </sizepolicy>
577
- </property>
578
- <property name="minimumSize">
579
- <size>
580
- <width>125</width>
581
- <height>0</height>
582
- </size>
583
- </property>
584
- <property name="maximumSize">
585
- <size>
586
- <width>16777215</width>
587
- <height>16777215</height>
588
- </size>
589
- </property>
590
- <property name="font">
591
- <font>
592
- <family>Arial</family>
593
- <pointsize>12</pointsize>
594
- <weight>50</weight>
595
- <italic>false</italic>
596
- <bold>false</bold>
597
- </font>
598
- </property>
599
- <property name="text">
600
- <string>NCBI File Search</string>
601
- </property>
602
- </widget>
603
- </item>
604
- <item row="1" column="1" colspan="2">
605
- <spacer name="verticalSpacer_5">
606
- <property name="orientation">
607
- <enum>Qt::Vertical</enum>
608
- </property>
609
- <property name="sizeType">
610
- <enum>QSizePolicy::Fixed</enum>
611
- </property>
612
- <property name="sizeHint" stdset="0">
613
- <size>
614
- <width>10</width>
615
- <height>10</height>
616
- </size>
617
- </property>
618
- </spacer>
619
- </item>
620
- </layout>
621
- </widget>
622
- </item>
623
- <item row="0" column="1" rowspan="4">
624
- <widget class="QGroupBox" name="Step3">
625
- <property name="sizePolicy">
626
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
627
- <horstretch>0</horstretch>
628
- <verstretch>0</verstretch>
629
- </sizepolicy>
630
- </property>
631
- <property name="minimumSize">
632
- <size>
633
- <width>0</width>
634
- <height>0</height>
635
- </size>
636
- </property>
637
- <property name="maximumSize">
638
- <size>
639
- <width>16777215</width>
640
- <height>16777215</height>
641
- </size>
642
- </property>
643
- <property name="font">
644
- <font>
645
- <family>Arial</family>
646
- <pointsize>12</pointsize>
647
- <weight>50</weight>
648
- <italic>false</italic>
649
- <bold>false</bold>
650
- </font>
651
- </property>
652
- <property name="styleSheet">
653
- <string notr="true"/>
654
- </property>
655
- <property name="title">
656
- <string>Step 3: Search and Find Targets</string>
657
- </property>
658
- <layout class="QGridLayout" name="gridLayout_4">
659
- <property name="topMargin">
660
- <number>15</number>
661
- </property>
662
- <item row="1" column="2">
663
- <widget class="QRadioButton" name="radioButton_Sequence">
664
- <property name="text">
665
- <string>Sequence</string>
666
- </property>
667
- </widget>
668
- </item>
669
- <item row="2" column="0" colspan="3">
670
- <widget class="QPlainTextEdit" name="geneEntryField">
671
- <property name="sizePolicy">
672
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
673
- <horstretch>0</horstretch>
674
- <verstretch>0</verstretch>
675
- </sizepolicy>
676
- </property>
677
- <property name="minimumSize">
678
- <size>
679
- <width>250</width>
680
- <height>0</height>
681
- </size>
682
- </property>
683
- <property name="maximumSize">
684
- <size>
685
- <width>16777215</width>
686
- <height>16777215</height>
687
- </size>
688
- </property>
689
- <property name="font">
690
- <font>
691
- <family>Arial</family>
692
- <pointsize>12</pointsize>
693
- <weight>50</weight>
694
- <italic>false</italic>
695
- <bold>false</bold>
696
- </font>
697
- </property>
698
- </widget>
699
- </item>
700
- <item row="5" column="0" colspan="3">
701
- <widget class="QProgressBar" name="progressBar">
702
- <property name="sizePolicy">
703
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
704
- <horstretch>0</horstretch>
705
- <verstretch>0</verstretch>
706
- </sizepolicy>
707
- </property>
708
- <property name="minimumSize">
709
- <size>
710
- <width>0</width>
711
- <height>0</height>
712
- </size>
713
- </property>
714
- <property name="value">
715
- <number>24</number>
716
- </property>
717
- </widget>
718
- </item>
719
- <item row="3" column="0" colspan="3">
720
- <widget class="QPushButton" name="pushButton_FindTargets">
721
- <property name="enabled">
722
- <bool>true</bool>
723
- </property>
724
- <property name="sizePolicy">
725
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
726
- <horstretch>0</horstretch>
727
- <verstretch>0</verstretch>
728
- </sizepolicy>
729
- </property>
730
- <property name="minimumSize">
731
- <size>
732
- <width>0</width>
733
- <height>0</height>
734
- </size>
735
- </property>
736
- <property name="maximumSize">
737
- <size>
738
- <width>16777215</width>
739
- <height>16777215</height>
740
- </size>
741
- </property>
742
- <property name="text">
743
- <string>Find Targets</string>
744
- </property>
745
- </widget>
746
- </item>
747
- <item row="0" column="0" colspan="2">
748
- <spacer name="verticalSpacer_3">
749
- <property name="orientation">
750
- <enum>Qt::Vertical</enum>
751
- </property>
752
- <property name="sizeType">
753
- <enum>QSizePolicy::Fixed</enum>
754
- </property>
755
- <property name="sizeHint" stdset="0">
756
- <size>
757
- <width>10</width>
758
- <height>10</height>
759
- </size>
760
- </property>
761
- </spacer>
762
- </item>
763
- <item row="1" column="0">
764
- <widget class="QRadioButton" name="radioButton_Gene">
765
- <property name="sizePolicy">
766
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
767
- <horstretch>0</horstretch>
768
- <verstretch>0</verstretch>
769
- </sizepolicy>
770
- </property>
771
- <property name="font">
772
- <font>
773
- <family>Arial</family>
774
- <pointsize>12</pointsize>
775
- <weight>50</weight>
776
- <italic>false</italic>
777
- <bold>false</bold>
778
- </font>
779
- </property>
780
- <property name="text">
781
- <string>Feature</string>
782
- </property>
783
- <property name="checked">
784
- <bool>true</bool>
785
- </property>
786
- </widget>
787
- </item>
788
- <item row="1" column="1">
789
- <widget class="QRadioButton" name="radioButton_Position">
790
- <property name="sizePolicy">
791
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
792
- <horstretch>0</horstretch>
793
- <verstretch>0</verstretch>
794
- </sizepolicy>
795
- </property>
796
- <property name="font">
797
- <font>
798
- <family>Arial</family>
799
- <pointsize>12</pointsize>
800
- <weight>50</weight>
801
- <italic>false</italic>
802
- <bold>false</bold>
803
- </font>
804
- </property>
805
- <property name="text">
806
- <string>Position</string>
807
- </property>
808
- <property name="iconSize">
809
- <size>
810
- <width>16</width>
811
- <height>16</height>
812
- </size>
813
- </property>
814
- </widget>
815
- </item>
816
- <item row="8" column="0" colspan="2">
817
- <spacer name="verticalSpacer_4">
818
- <property name="orientation">
819
- <enum>Qt::Vertical</enum>
820
- </property>
821
- <property name="sizeType">
822
- <enum>QSizePolicy::Fixed</enum>
823
- </property>
824
- <property name="sizeHint" stdset="0">
825
- <size>
826
- <width>10</width>
827
- <height>10</height>
828
- </size>
829
- </property>
830
- </spacer>
831
- </item>
832
- <item row="6" column="0" colspan="3">
833
- <layout class="QHBoxLayout" name="horizontalLayout">
834
- <item>
835
- <widget class="QPushButton" name="pushButton_ViewTargets">
836
- <property name="sizePolicy">
837
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
838
- <horstretch>0</horstretch>
839
- <verstretch>0</verstretch>
840
- </sizepolicy>
841
- </property>
842
- <property name="minimumSize">
843
- <size>
844
- <width>0</width>
845
- <height>0</height>
846
- </size>
847
- </property>
848
- <property name="text">
849
- <string>View Targets</string>
850
- </property>
851
- </widget>
852
- </item>
853
- <item>
854
- <widget class="QPushButton" name="GenerateLibrary">
855
- <property name="sizePolicy">
856
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
857
- <horstretch>0</horstretch>
858
- <verstretch>0</verstretch>
859
- </sizepolicy>
860
- </property>
861
- <property name="minimumSize">
862
- <size>
863
- <width>0</width>
864
- <height>0</height>
865
- </size>
866
- </property>
867
- <property name="maximumSize">
868
- <size>
869
- <width>16777215</width>
870
- <height>16777215</height>
871
- </size>
872
- </property>
873
- <property name="text">
874
- <string>Generate Library</string>
875
- </property>
876
- </widget>
877
- </item>
878
- </layout>
879
- </item>
880
- </layout>
881
- </widget>
882
- </item>
883
- </layout>
884
- </item>
885
- <item row="1" column="0">
886
- <widget class="QLabel" name="label_6">
887
- <property name="minimumSize">
888
- <size>
889
- <width>50</width>
890
- <height>0</height>
891
- </size>
892
- </property>
893
- <property name="maximumSize">
894
- <size>
895
- <width>50</width>
896
- <height>16777215</height>
897
- </size>
898
- </property>
899
- <property name="text">
900
- <string/>
901
- </property>
902
- </widget>
903
- </item>
904
- <item row="5" column="3" rowspan="2">
905
- <spacer name="horizontalSpacer_2">
906
- <property name="orientation">
907
- <enum>Qt::Horizontal</enum>
908
- </property>
909
- <property name="sizeType">
910
- <enum>QSizePolicy::Fixed</enum>
911
- </property>
912
- <property name="sizeHint" stdset="0">
913
- <size>
914
- <width>20</width>
915
- <height>20</height>
916
- </size>
917
- </property>
918
- </spacer>
919
- </item>
920
- <item row="7" column="1" colspan="2">
921
- <spacer name="verticalSpacer_2">
922
- <property name="orientation">
923
- <enum>Qt::Vertical</enum>
924
- </property>
925
- <property name="sizeType">
926
- <enum>QSizePolicy::Fixed</enum>
927
- </property>
928
- <property name="sizeHint" stdset="0">
929
- <size>
930
- <width>20</width>
931
- <height>20</height>
932
- </size>
933
- </property>
934
- </spacer>
935
- </item>
936
- <item row="3" column="1" colspan="2">
937
- <widget class="QGroupBox" name="CASPER_Navigation">
938
- <property name="sizePolicy">
939
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
940
- <horstretch>0</horstretch>
941
- <verstretch>0</verstretch>
942
- </sizepolicy>
943
- </property>
944
- <property name="title">
945
- <string>CASPER Navigation</string>
946
- </property>
947
- <layout class="QGridLayout" name="gridLayout_2">
948
- <item row="1" column="1">
949
- <widget class="QPushButton" name="newEndo_button">
950
- <property name="text">
951
- <string>Define New Endonuclease</string>
952
- </property>
953
- </widget>
954
- </item>
955
- <item row="1" column="0">
956
- <widget class="QPushButton" name="newGenome_button">
957
- <property name="text">
958
- <string>Analyze New Genome</string>
959
- </property>
960
- </widget>
961
- </item>
962
- <item row="2" column="0">
963
- <widget class="QPushButton" name="multitargeting_button">
964
- <property name="text">
965
- <string>Multitargeting Analysis</string>
966
- </property>
967
- </widget>
968
- </item>
969
- <item row="2" column="1">
970
- <widget class="QPushButton" name="populationAnalysis_button">
971
- <property name="text">
972
- <string>Population Analysis</string>
973
- </property>
974
- </widget>
975
- </item>
976
- <item row="0" column="0" colspan="2">
977
- <spacer name="verticalSpacer_10">
978
- <property name="orientation">
979
- <enum>Qt::Vertical</enum>
980
- </property>
981
- <property name="sizeType">
982
- <enum>QSizePolicy::Fixed</enum>
983
- </property>
984
- <property name="sizeHint" stdset="0">
985
- <size>
986
- <width>10</width>
987
- <height>10</height>
988
- </size>
989
- </property>
990
- </spacer>
991
- </item>
992
- <item row="3" column="0" colspan="2">
993
- <spacer name="verticalSpacer_9">
994
- <property name="orientation">
995
- <enum>Qt::Vertical</enum>
996
- </property>
997
- <property name="sizeType">
998
- <enum>QSizePolicy::Fixed</enum>
999
- </property>
1000
- <property name="sizeHint" stdset="0">
1001
- <size>
1002
- <width>10</width>
1003
- <height>10</height>
1004
- </size>
1005
- </property>
1006
- </spacer>
1007
- </item>
1008
- </layout>
1009
- </widget>
1010
- </item>
1011
- </layout>
1012
- </widget>
1013
- <widget class="QMenuBar" name="menubar">
1014
- <property name="geometry">
1015
- <rect>
1016
- <x>0</x>
1017
- <y>0</y>
1018
- <width>1021</width>
1019
- <height>24</height>
1020
- </rect>
1021
- </property>
1022
- <property name="font">
1023
- <font>
1024
- <family>Arial</family>
1025
- <pointsize>8</pointsize>
1026
- </font>
1027
- </property>
1028
- <widget class="QMenu" name="menuFile">
1029
- <property name="title">
1030
- <string>File</string>
1031
- </property>
1032
- <addaction name="separator"/>
1033
- <addaction name="actionExit"/>
1034
- </widget>
1035
- <widget class="QMenu" name="menuGenome">
1036
- <property name="title">
1037
- <string>Genome</string>
1038
- </property>
1039
- <addaction name="actionChange_Directory"/>
1040
- <addaction name="actionOpen_Genome_Browser"/>
1041
- </widget>
1042
- <widget class="QMenu" name="menuTools">
1043
- <property name="title">
1044
- <string>Tools</string>
1045
- </property>
1046
- <addaction name="actionNCBI_BLAST"/>
1047
- </widget>
1048
- <widget class="QMenu" name="menuWindow">
1049
- <property name="title">
1050
- <string>Web Links</string>
1051
- </property>
1052
- <addaction name="actionNCBI"/>
1053
- </widget>
1054
- <widget class="QMenu" name="menuHelp">
1055
- <property name="title">
1056
- <string>Help</string>
1057
- </property>
1058
- <addaction name="visit_repo"/>
1059
- </widget>
1060
- <addaction name="menuFile"/>
1061
- <addaction name="menuGenome"/>
1062
- <addaction name="menuTools"/>
1063
- <addaction name="menuWindow"/>
1064
- <addaction name="menuHelp"/>
1065
- </widget>
1066
- <widget class="QStatusBar" name="statusbar">
1067
- <property name="font">
1068
- <font>
1069
- <family>Arial</family>
1070
- <pointsize>8</pointsize>
1071
- </font>
1072
- </property>
1073
- </widget>
1074
- <action name="actionNew">
1075
- <property name="text">
1076
- <string>New</string>
1077
- </property>
1078
- </action>
1079
- <action name="actionOpen">
1080
- <property name="text">
1081
- <string>Open</string>
1082
- </property>
1083
- </action>
1084
- <action name="actionOpen_Recent">
1085
- <property name="text">
1086
- <string>Open Recent...</string>
1087
- </property>
1088
- </action>
1089
- <action name="actionSave">
1090
- <property name="text">
1091
- <string>Save</string>
1092
- </property>
1093
- </action>
1094
- <action name="actionExit">
1095
- <property name="text">
1096
- <string>Exit</string>
1097
- </property>
1098
- <property name="font">
1099
- <font>
1100
- <family>Arial</family>
1101
- </font>
1102
- </property>
1103
- </action>
1104
- <action name="actionUndo">
1105
- <property name="text">
1106
- <string>Undo</string>
1107
- </property>
1108
- </action>
1109
- <action name="actionCut">
1110
- <property name="text">
1111
- <string>Cut</string>
1112
- </property>
1113
- </action>
1114
- <action name="actionCopy">
1115
- <property name="text">
1116
- <string>Copy</string>
1117
- </property>
1118
- </action>
1119
- <action name="actionPaste">
1120
- <property name="text">
1121
- <string>Paste</string>
1122
- </property>
1123
- </action>
1124
- <action name="actionCut_Rev_Com">
1125
- <property name="text">
1126
- <string>Cut Rev-Com</string>
1127
- </property>
1128
- </action>
1129
- <action name="actionCopy_Rev_Com">
1130
- <property name="text">
1131
- <string>Copy Rev-Com</string>
1132
- </property>
1133
- </action>
1134
- <action name="actionPaste_Rev_Com">
1135
- <property name="text">
1136
- <string>Paste Rev-Com</string>
1137
- </property>
1138
- </action>
1139
- <action name="actionUpload_New_Genome">
1140
- <property name="text">
1141
- <string>Analyze New Genome</string>
1142
- </property>
1143
- <property name="font">
1144
- <font>
1145
- <family>Arial</family>
1146
- </font>
1147
- </property>
1148
- </action>
1149
- <action name="actionUpload_New_Endonuclease">
1150
- <property name="text">
1151
- <string>Define New Endonuclease</string>
1152
- </property>
1153
- <property name="font">
1154
- <font>
1155
- <family>Arial</family>
1156
- </font>
1157
- </property>
1158
- </action>
1159
- <action name="actionOpen_Genome_Browser">
1160
- <property name="text">
1161
- <string>Open Genome Browser</string>
1162
- </property>
1163
- <property name="font">
1164
- <font>
1165
- <family>Arial</family>
1166
- </font>
1167
- </property>
1168
- </action>
1169
- <action name="actionChange_Directory">
1170
- <property name="text">
1171
- <string>Change Database Directory</string>
1172
- </property>
1173
- <property name="font">
1174
- <font>
1175
- <family>Arial</family>
1176
- </font>
1177
- </property>
1178
- </action>
1179
- <action name="actionNCBI_BLAST">
1180
- <property name="text">
1181
- <string>NCBI BLAST</string>
1182
- </property>
1183
- </action>
1184
- <action name="actionExcel_csv">
1185
- <property name="text">
1186
- <string>Excel (.csv)</string>
1187
- </property>
1188
- </action>
1189
- <action name="actionIDT_Order">
1190
- <property name="text">
1191
- <string>IDT Order</string>
1192
- </property>
1193
- </action>
1194
- <action name="actionMultitargeting">
1195
- <property name="text">
1196
- <string>Multitargeting Analysis</string>
1197
- </property>
1198
- <property name="font">
1199
- <font>
1200
- <family>Arial</family>
1201
- </font>
1202
- </property>
1203
- </action>
1204
- <action name="actionPopulation_Analysis">
1205
- <property name="text">
1206
- <string>Population Analysis</string>
1207
- </property>
1208
- </action>
1209
- <action name="actionComplete_Target_Analysis">
1210
- <property name="text">
1211
- <string>Complete Target Analysis</string>
1212
- </property>
1213
- </action>
1214
- <action name="actionNCBI">
1215
- <property name="text">
1216
- <string>National Center for BioTechnology Information</string>
1217
- </property>
1218
- <property name="font">
1219
- <font>
1220
- <family>Arial</family>
1221
- </font>
1222
- </property>
1223
- </action>
1224
- <action name="actionCasper2">
1225
- <property name="text">
1226
- <string>CASPER Online</string>
1227
- </property>
1228
- <property name="font">
1229
- <font>
1230
- <family>Arial</family>
1231
- </font>
1232
- </property>
1233
- </action>
1234
- <action name="actionCo_Targeting">
1235
- <property name="text">
1236
- <string>Co-Targeting</string>
1237
- </property>
1238
- </action>
1239
- <action name="visit_repo">
1240
- <property name="text">
1241
- <string>Visit Repository</string>
1242
- </property>
1243
- <property name="font">
1244
- <font>
1245
- <family>Arial</family>
1246
- </font>
1247
- </property>
1248
- </action>
1249
- </widget>
1250
- <tabstops>
1251
- <tabstop>orgChoice</tabstop>
1252
- <tabstop>endoChoice</tabstop>
1253
- <tabstop>launch_ncbi_button</tabstop>
1254
- <tabstop>annotation_files</tabstop>
1255
- <tabstop>radioButton_Gene</tabstop>
1256
- <tabstop>radioButton_Position</tabstop>
1257
- <tabstop>geneEntryField</tabstop>
1258
- <tabstop>pushButton_FindTargets</tabstop>
1259
- </tabstops>
1260
- <resources/>
1261
- <connections/>
1262
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/NewGenome.ui DELETED
@@ -1,1080 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>811</width>
10
- <height>857</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_3">
23
- <item row="1" column="2">
24
- <widget class="QLabel" name="label_8">
25
- <property name="minimumSize">
26
- <size>
27
- <width>0</width>
28
- <height>0</height>
29
- </size>
30
- </property>
31
- <property name="maximumSize">
32
- <size>
33
- <width>16777215</width>
34
- <height>50</height>
35
- </size>
36
- </property>
37
- <property name="font">
38
- <font>
39
- <family>Arial</family>
40
- <pointsize>12</pointsize>
41
- <weight>75</weight>
42
- <italic>false</italic>
43
- <bold>true</bold>
44
- </font>
45
- </property>
46
- <property name="styleSheet">
47
- <string notr="true"/>
48
- </property>
49
- <property name="text">
50
- <string>New Genome</string>
51
- </property>
52
- <property name="scaledContents">
53
- <bool>false</bool>
54
- </property>
55
- </widget>
56
- </item>
57
- <item row="0" column="2" colspan="2">
58
- <spacer name="verticalSpacer">
59
- <property name="orientation">
60
- <enum>Qt::Vertical</enum>
61
- </property>
62
- <property name="sizeType">
63
- <enum>QSizePolicy::Fixed</enum>
64
- </property>
65
- <property name="sizeHint" stdset="0">
66
- <size>
67
- <width>20</width>
68
- <height>20</height>
69
- </size>
70
- </property>
71
- </spacer>
72
- </item>
73
- <item row="0" column="0" rowspan="10">
74
- <spacer name="horizontalSpacer_2">
75
- <property name="orientation">
76
- <enum>Qt::Horizontal</enum>
77
- </property>
78
- <property name="sizeType">
79
- <enum>QSizePolicy::Fixed</enum>
80
- </property>
81
- <property name="sizeHint" stdset="0">
82
- <size>
83
- <width>20</width>
84
- <height>20</height>
85
- </size>
86
- </property>
87
- </spacer>
88
- </item>
89
- <item row="1" column="3" alignment="Qt::AlignRight">
90
- <widget class="QLabel" name="label_16">
91
- <property name="maximumSize">
92
- <size>
93
- <width>16777215</width>
94
- <height>33</height>
95
- </size>
96
- </property>
97
- <property name="text">
98
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;* Required&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
99
- </property>
100
- </widget>
101
- </item>
102
- <item row="9" column="2" colspan="2">
103
- <spacer name="verticalSpacer_2">
104
- <property name="orientation">
105
- <enum>Qt::Vertical</enum>
106
- </property>
107
- <property name="sizeType">
108
- <enum>QSizePolicy::Fixed</enum>
109
- </property>
110
- <property name="sizeHint" stdset="0">
111
- <size>
112
- <width>20</width>
113
- <height>20</height>
114
- </size>
115
- </property>
116
- </spacer>
117
- </item>
118
- <item row="3" column="2" colspan="2">
119
- <widget class="Line" name="line_2">
120
- <property name="lineWidth">
121
- <number>2</number>
122
- </property>
123
- <property name="midLineWidth">
124
- <number>1</number>
125
- </property>
126
- <property name="orientation">
127
- <enum>Qt::Horizontal</enum>
128
- </property>
129
- </widget>
130
- </item>
131
- <item row="0" column="4" rowspan="10">
132
- <spacer name="horizontalSpacer_3">
133
- <property name="orientation">
134
- <enum>Qt::Horizontal</enum>
135
- </property>
136
- <property name="sizeType">
137
- <enum>QSizePolicy::Fixed</enum>
138
- </property>
139
- <property name="sizeHint" stdset="0">
140
- <size>
141
- <width>20</width>
142
- <height>20</height>
143
- </size>
144
- </property>
145
- </spacer>
146
- </item>
147
- <item row="8" column="2" colspan="2">
148
- <layout class="QHBoxLayout" name="horizontalLayout_5">
149
- <item alignment="Qt::AlignLeft">
150
- <widget class="QPushButton" name="contButton">
151
- <property name="sizePolicy">
152
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
153
- <horstretch>0</horstretch>
154
- <verstretch>0</verstretch>
155
- </sizepolicy>
156
- </property>
157
- <property name="minimumSize">
158
- <size>
159
- <width>125</width>
160
- <height>0</height>
161
- </size>
162
- </property>
163
- <property name="maximumSize">
164
- <size>
165
- <width>16777215</width>
166
- <height>16777215</height>
167
- </size>
168
- </property>
169
- <property name="font">
170
- <font>
171
- <family>Arial</family>
172
- <pointsize>12</pointsize>
173
- <weight>50</weight>
174
- <italic>false</italic>
175
- <bold>false</bold>
176
- </font>
177
- </property>
178
- <property name="styleSheet">
179
- <string notr="true"/>
180
- </property>
181
- <property name="text">
182
- <string>Exit</string>
183
- </property>
184
- </widget>
185
- </item>
186
- <item alignment="Qt::AlignRight">
187
- <widget class="QPushButton" name="resetButton">
188
- <property name="sizePolicy">
189
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
190
- <horstretch>0</horstretch>
191
- <verstretch>0</verstretch>
192
- </sizepolicy>
193
- </property>
194
- <property name="minimumSize">
195
- <size>
196
- <width>125</width>
197
- <height>0</height>
198
- </size>
199
- </property>
200
- <property name="maximumSize">
201
- <size>
202
- <width>16777215</width>
203
- <height>16777215</height>
204
- </size>
205
- </property>
206
- <property name="text">
207
- <string>Reset Form</string>
208
- </property>
209
- </widget>
210
- </item>
211
- </layout>
212
- </item>
213
- <item row="6" column="2" colspan="2">
214
- <widget class="QGroupBox" name="Step3">
215
- <property name="sizePolicy">
216
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
217
- <horstretch>0</horstretch>
218
- <verstretch>0</verstretch>
219
- </sizepolicy>
220
- </property>
221
- <property name="minimumSize">
222
- <size>
223
- <width>0</width>
224
- <height>0</height>
225
- </size>
226
- </property>
227
- <property name="maximumSize">
228
- <size>
229
- <width>16777215</width>
230
- <height>16777215</height>
231
- </size>
232
- </property>
233
- <property name="font">
234
- <font>
235
- <family>Arial</family>
236
- <pointsize>12</pointsize>
237
- <weight>50</weight>
238
- <italic>false</italic>
239
- <bold>false</bold>
240
- </font>
241
- </property>
242
- <property name="styleSheet">
243
- <string notr="true"/>
244
- </property>
245
- <property name="title">
246
- <string>Step 3: Select and Run Jobs</string>
247
- </property>
248
- <layout class="QGridLayout" name="gridLayout_8">
249
- <property name="topMargin">
250
- <number>15</number>
251
- </property>
252
- <item row="0" column="0">
253
- <spacer name="verticalSpacer_7">
254
- <property name="orientation">
255
- <enum>Qt::Vertical</enum>
256
- </property>
257
- <property name="sizeType">
258
- <enum>QSizePolicy::Fixed</enum>
259
- </property>
260
- <property name="sizeHint" stdset="0">
261
- <size>
262
- <width>10</width>
263
- <height>10</height>
264
- </size>
265
- </property>
266
- </spacer>
267
- </item>
268
- <item row="1" column="0">
269
- <layout class="QHBoxLayout" name="horizontalLayout_6">
270
- <item>
271
- <layout class="QHBoxLayout" name="horizontalLayout_8">
272
- <item>
273
- <widget class="QPushButton" name="clearButton">
274
- <property name="sizePolicy">
275
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
276
- <horstretch>0</horstretch>
277
- <verstretch>0</verstretch>
278
- </sizepolicy>
279
- </property>
280
- <property name="minimumSize">
281
- <size>
282
- <width>0</width>
283
- <height>0</height>
284
- </size>
285
- </property>
286
- <property name="text">
287
- <string>Clear All</string>
288
- </property>
289
- </widget>
290
- </item>
291
- <item>
292
- <widget class="QPushButton" name="remove_job">
293
- <property name="sizePolicy">
294
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
295
- <horstretch>0</horstretch>
296
- <verstretch>0</verstretch>
297
- </sizepolicy>
298
- </property>
299
- <property name="minimumSize">
300
- <size>
301
- <width>0</width>
302
- <height>0</height>
303
- </size>
304
- </property>
305
- <property name="text">
306
- <string>Remove Job</string>
307
- </property>
308
- </widget>
309
- </item>
310
- <item>
311
- <widget class="QPushButton" name="runButton">
312
- <property name="sizePolicy">
313
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
314
- <horstretch>0</horstretch>
315
- <verstretch>0</verstretch>
316
- </sizepolicy>
317
- </property>
318
- <property name="minimumSize">
319
- <size>
320
- <width>0</width>
321
- <height>0</height>
322
- </size>
323
- </property>
324
- <property name="text">
325
- <string>Run All</string>
326
- </property>
327
- </widget>
328
- </item>
329
- </layout>
330
- </item>
331
- <item>
332
- <layout class="QHBoxLayout" name="horizontalLayout_7">
333
- <item>
334
- <widget class="QLabel" name="label_4">
335
- <property name="sizePolicy">
336
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
337
- <horstretch>0</horstretch>
338
- <verstretch>0</verstretch>
339
- </sizepolicy>
340
- </property>
341
- <property name="text">
342
- <string>Progress Output</string>
343
- </property>
344
- <property name="alignment">
345
- <set>Qt::AlignCenter</set>
346
- </property>
347
- </widget>
348
- </item>
349
- </layout>
350
- </item>
351
- </layout>
352
- </item>
353
- <item row="2" column="0">
354
- <layout class="QHBoxLayout" name="horizontalLayout_2">
355
- <item>
356
- <layout class="QVBoxLayout" name="verticalLayout_3">
357
- <item>
358
- <widget class="QTableWidget" name="job_Table">
359
- <property name="sizePolicy">
360
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
361
- <horstretch>0</horstretch>
362
- <verstretch>0</verstretch>
363
- </sizepolicy>
364
- </property>
365
- <property name="minimumSize">
366
- <size>
367
- <width>0</width>
368
- <height>0</height>
369
- </size>
370
- </property>
371
- <property name="maximumSize">
372
- <size>
373
- <width>16777215</width>
374
- <height>16777215</height>
375
- </size>
376
- </property>
377
- <attribute name="horizontalHeaderDefaultSectionSize">
378
- <number>165</number>
379
- </attribute>
380
- <attribute name="horizontalHeaderMinimumSectionSize">
381
- <number>50</number>
382
- </attribute>
383
- <column>
384
- <property name="text">
385
- <string>Job Queue</string>
386
- </property>
387
- <property name="textAlignment">
388
- <set>AlignCenter</set>
389
- </property>
390
- </column>
391
- <column>
392
- <property name="text">
393
- <string>Job in Progress</string>
394
- </property>
395
- <property name="textAlignment">
396
- <set>AlignCenter</set>
397
- </property>
398
- </column>
399
- <column>
400
- <property name="text">
401
- <string>Completed Jobs</string>
402
- </property>
403
- <property name="textAlignment">
404
- <set>AlignCenter</set>
405
- </property>
406
- </column>
407
- </widget>
408
- </item>
409
- </layout>
410
- </item>
411
- <item>
412
- <layout class="QVBoxLayout" name="verticalLayout">
413
- <item>
414
- <layout class="QHBoxLayout" name="horizontalLayout_4">
415
- <property name="sizeConstraint">
416
- <enum>QLayout::SetDefaultConstraint</enum>
417
- </property>
418
- <item>
419
- <widget class="QTextBrowser" name="output_browser">
420
- <property name="sizePolicy">
421
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
422
- <horstretch>0</horstretch>
423
- <verstretch>0</verstretch>
424
- </sizepolicy>
425
- </property>
426
- <property name="minimumSize">
427
- <size>
428
- <width>0</width>
429
- <height>0</height>
430
- </size>
431
- </property>
432
- <property name="verticalScrollBarPolicy">
433
- <enum>Qt::ScrollBarAsNeeded</enum>
434
- </property>
435
- <property name="horizontalScrollBarPolicy">
436
- <enum>Qt::ScrollBarAsNeeded</enum>
437
- </property>
438
- <property name="sizeAdjustPolicy">
439
- <enum>QAbstractScrollArea::AdjustIgnored</enum>
440
- </property>
441
- <property name="lineWrapMode">
442
- <enum>QTextEdit::NoWrap</enum>
443
- </property>
444
- </widget>
445
- </item>
446
- </layout>
447
- </item>
448
- <item>
449
- <widget class="QProgressBar" name="progressBar">
450
- <property name="minimumSize">
451
- <size>
452
- <width>0</width>
453
- <height>0</height>
454
- </size>
455
- </property>
456
- <property name="value">
457
- <number>0</number>
458
- </property>
459
- </widget>
460
- </item>
461
- </layout>
462
- </item>
463
- </layout>
464
- </item>
465
- <item row="3" column="0">
466
- <spacer name="verticalSpacer_8">
467
- <property name="orientation">
468
- <enum>Qt::Vertical</enum>
469
- </property>
470
- <property name="sizeType">
471
- <enum>QSizePolicy::Fixed</enum>
472
- </property>
473
- <property name="sizeHint" stdset="0">
474
- <size>
475
- <width>10</width>
476
- <height>10</height>
477
- </size>
478
- </property>
479
- </spacer>
480
- </item>
481
- </layout>
482
- </widget>
483
- </item>
484
- <item row="5" column="2" colspan="2">
485
- <widget class="QGroupBox" name="Step2">
486
- <property name="sizePolicy">
487
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
488
- <horstretch>0</horstretch>
489
- <verstretch>0</verstretch>
490
- </sizepolicy>
491
- </property>
492
- <property name="minimumSize">
493
- <size>
494
- <width>0</width>
495
- <height>0</height>
496
- </size>
497
- </property>
498
- <property name="maximumSize">
499
- <size>
500
- <width>16777215</width>
501
- <height>16777215</height>
502
- </size>
503
- </property>
504
- <property name="styleSheet">
505
- <string notr="true"/>
506
- </property>
507
- <property name="title">
508
- <string>Step 2: Select File and Add Job to Queue</string>
509
- </property>
510
- <layout class="QGridLayout" name="gridLayout_4">
511
- <property name="topMargin">
512
- <number>15</number>
513
- </property>
514
- <item row="0" column="0">
515
- <spacer name="verticalSpacer_5">
516
- <property name="orientation">
517
- <enum>Qt::Vertical</enum>
518
- </property>
519
- <property name="sizeType">
520
- <enum>QSizePolicy::Fixed</enum>
521
- </property>
522
- <property name="sizeHint" stdset="0">
523
- <size>
524
- <width>10</width>
525
- <height>10</height>
526
- </size>
527
- </property>
528
- </spacer>
529
- </item>
530
- <item row="2" column="0">
531
- <spacer name="verticalSpacer_6">
532
- <property name="orientation">
533
- <enum>Qt::Vertical</enum>
534
- </property>
535
- <property name="sizeType">
536
- <enum>QSizePolicy::Fixed</enum>
537
- </property>
538
- <property name="sizeHint" stdset="0">
539
- <size>
540
- <width>10</width>
541
- <height>10</height>
542
- </size>
543
- </property>
544
- </spacer>
545
- </item>
546
- <item row="1" column="0">
547
- <layout class="QVBoxLayout" name="verticalLayout_5">
548
- <item>
549
- <widget class="QLabel" name="label_7">
550
- <property name="sizePolicy">
551
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
552
- <horstretch>0</horstretch>
553
- <verstretch>0</verstretch>
554
- </sizepolicy>
555
- </property>
556
- <property name="text">
557
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;* &lt;/span&gt;Select Local FASTA/FNA File:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
558
- </property>
559
- </widget>
560
- </item>
561
- <item>
562
- <layout class="QHBoxLayout" name="horizontalLayout">
563
- <item>
564
- <layout class="QHBoxLayout" name="horizontalLayout_10">
565
- <property name="sizeConstraint">
566
- <enum>QLayout::SetMinimumSize</enum>
567
- </property>
568
- <item>
569
- <widget class="QPushButton" name="NCBI_File_Search">
570
- <property name="sizePolicy">
571
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
572
- <horstretch>0</horstretch>
573
- <verstretch>0</verstretch>
574
- </sizepolicy>
575
- </property>
576
- <property name="minimumSize">
577
- <size>
578
- <width>0</width>
579
- <height>0</height>
580
- </size>
581
- </property>
582
- <property name="text">
583
- <string>NCBI Tool</string>
584
- </property>
585
- </widget>
586
- </item>
587
- <item>
588
- <widget class="QPushButton" name="browseForFile">
589
- <property name="sizePolicy">
590
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
591
- <horstretch>0</horstretch>
592
- <verstretch>0</verstretch>
593
- </sizepolicy>
594
- </property>
595
- <property name="minimumSize">
596
- <size>
597
- <width>0</width>
598
- <height>0</height>
599
- </size>
600
- </property>
601
- <property name="text">
602
- <string>Browse</string>
603
- </property>
604
- </widget>
605
- </item>
606
- </layout>
607
- </item>
608
- <item>
609
- <widget class="QLineEdit" name="selectedFile">
610
- <property name="sizePolicy">
611
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
612
- <horstretch>0</horstretch>
613
- <verstretch>0</verstretch>
614
- </sizepolicy>
615
- </property>
616
- <property name="inputMask">
617
- <string/>
618
- </property>
619
- <property name="text">
620
- <string/>
621
- </property>
622
- <property name="readOnly">
623
- <bool>true</bool>
624
- </property>
625
- <property name="placeholderText">
626
- <string>Selected FASTA/FNA File</string>
627
- </property>
628
- </widget>
629
- </item>
630
- <item>
631
- <layout class="QHBoxLayout" name="horizontalLayout_9">
632
- <property name="sizeConstraint">
633
- <enum>QLayout::SetMinimumSize</enum>
634
- </property>
635
- </layout>
636
- </item>
637
- </layout>
638
- </item>
639
- <item>
640
- <layout class="QHBoxLayout" name="horizontalLayout_11">
641
- <item>
642
- <widget class="QPushButton" name="submitButton">
643
- <property name="sizePolicy">
644
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
645
- <horstretch>0</horstretch>
646
- <verstretch>0</verstretch>
647
- </sizepolicy>
648
- </property>
649
- <property name="minimumSize">
650
- <size>
651
- <width>0</width>
652
- <height>0</height>
653
- </size>
654
- </property>
655
- <property name="text">
656
- <string>Add Job to Queue</string>
657
- </property>
658
- </widget>
659
- </item>
660
- <item>
661
- <widget class="QLabel" name="label_10">
662
- <property name="text">
663
- <string/>
664
- </property>
665
- </widget>
666
- </item>
667
- </layout>
668
- </item>
669
- </layout>
670
- </item>
671
- </layout>
672
- </widget>
673
- </item>
674
- <item row="4" column="2" colspan="2">
675
- <widget class="QGroupBox" name="Step1">
676
- <property name="sizePolicy">
677
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
678
- <horstretch>0</horstretch>
679
- <verstretch>0</verstretch>
680
- </sizepolicy>
681
- </property>
682
- <property name="minimumSize">
683
- <size>
684
- <width>0</width>
685
- <height>0</height>
686
- </size>
687
- </property>
688
- <property name="maximumSize">
689
- <size>
690
- <width>16777215</width>
691
- <height>16777215</height>
692
- </size>
693
- </property>
694
- <property name="font">
695
- <font>
696
- <family>Arial</family>
697
- <pointsize>12</pointsize>
698
- <weight>50</weight>
699
- <italic>false</italic>
700
- <bold>false</bold>
701
- </font>
702
- </property>
703
- <property name="styleSheet">
704
- <string notr="true"/>
705
- </property>
706
- <property name="title">
707
- <string>Step 1: Input Organism Info</string>
708
- </property>
709
- <layout class="QGridLayout" name="gridLayout_2">
710
- <property name="topMargin">
711
- <number>15</number>
712
- </property>
713
- <item row="1" column="6">
714
- <widget class="QLineEdit" name="seed_length">
715
- <property name="maximumSize">
716
- <size>
717
- <width>16777215</width>
718
- <height>16777215</height>
719
- </size>
720
- </property>
721
- <property name="readOnly">
722
- <bool>true</bool>
723
- </property>
724
- </widget>
725
- </item>
726
- <item row="4" column="0">
727
- <widget class="QLabel" name="label_14">
728
- <property name="text">
729
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
730
- </property>
731
- </widget>
732
- </item>
733
- <item row="4" column="5" colspan="2">
734
- <layout class="QHBoxLayout" name="horizontalLayout_3">
735
- <item>
736
- <widget class="QCheckBox" name="repeats_box">
737
- <property name="sizePolicy">
738
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
739
- <horstretch>0</horstretch>
740
- <verstretch>0</verstretch>
741
- </sizepolicy>
742
- </property>
743
- <property name="text">
744
- <string>Generate Repeats</string>
745
- </property>
746
- <property name="checked">
747
- <bool>true</bool>
748
- </property>
749
- </widget>
750
- </item>
751
- <item>
752
- <widget class="QCheckBox" name="mt">
753
- <property name="sizePolicy">
754
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
755
- <horstretch>0</horstretch>
756
- <verstretch>0</verstretch>
757
- </sizepolicy>
758
- </property>
759
- <property name="text">
760
- <string>Multi-threading</string>
761
- </property>
762
- <property name="checked">
763
- <bool>true</bool>
764
- </property>
765
- </widget>
766
- </item>
767
- </layout>
768
- </item>
769
- <item row="3" column="6">
770
- <widget class="QLineEdit" name="three_length">
771
- <property name="maximumSize">
772
- <size>
773
- <width>16777215</width>
774
- <height>16777215</height>
775
- </size>
776
- </property>
777
- <property name="readOnly">
778
- <bool>true</bool>
779
- </property>
780
- </widget>
781
- </item>
782
- <item row="3" column="5">
783
- <widget class="QLabel" name="label_9">
784
- <property name="sizePolicy">
785
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
786
- <horstretch>0</horstretch>
787
- <verstretch>0</verstretch>
788
- </sizepolicy>
789
- </property>
790
- <property name="toolTip">
791
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Length in nucleotides of gRNA sequence downstream (3')&lt;/p&gt;&lt;p&gt;of the seed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
792
- </property>
793
- <property name="text">
794
- <string>3' Length:</string>
795
- </property>
796
- </widget>
797
- </item>
798
- <item row="1" column="0">
799
- <widget class="QLabel" name="label_12">
800
- <property name="text">
801
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
802
- </property>
803
- </widget>
804
- </item>
805
- <item row="4" column="2">
806
- <widget class="QLineEdit" name="orgCode">
807
- <property name="maximumSize">
808
- <size>
809
- <width>16777215</width>
810
- <height>16777215</height>
811
- </size>
812
- </property>
813
- </widget>
814
- </item>
815
- <item row="1" column="5">
816
- <widget class="QLabel" name="label_2">
817
- <property name="sizePolicy">
818
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
819
- <horstretch>0</horstretch>
820
- <verstretch>0</verstretch>
821
- </sizepolicy>
822
- </property>
823
- <property name="toolTip">
824
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The length in nucleotides of the region of gRNA most crucial&lt;/p&gt;&lt;p&gt;for gRNA binding. CASPER uses this value to find repeated&lt;/p&gt;&lt;p&gt;gRNA sequences.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
825
- </property>
826
- <property name="text">
827
- <string>Seed Length:</string>
828
- </property>
829
- </widget>
830
- </item>
831
- <item row="2" column="0">
832
- <widget class="QLabel" name="label_6">
833
- <property name="text">
834
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
835
- </property>
836
- </widget>
837
- </item>
838
- <item row="2" column="1">
839
- <widget class="QLabel" name="Subspecies">
840
- <property name="sizePolicy">
841
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
842
- <horstretch>0</horstretch>
843
- <verstretch>0</verstretch>
844
- </sizepolicy>
845
- </property>
846
- <property name="toolTip">
847
- <string/>
848
- </property>
849
- <property name="text">
850
- <string>Strain:</string>
851
- </property>
852
- </widget>
853
- </item>
854
- <item row="1" column="4">
855
- <widget class="QLabel" name="label_15">
856
- <property name="text">
857
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
858
- </property>
859
- </widget>
860
- </item>
861
- <item row="2" column="2">
862
- <widget class="QLineEdit" name="strainName">
863
- <property name="maximumSize">
864
- <size>
865
- <width>16777215</width>
866
- <height>16777215</height>
867
- </size>
868
- </property>
869
- </widget>
870
- </item>
871
- <item row="3" column="1">
872
- <widget class="QLabel" name="endoNameLabel">
873
- <property name="sizePolicy">
874
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
875
- <horstretch>0</horstretch>
876
- <verstretch>0</verstretch>
877
- </sizepolicy>
878
- </property>
879
- <property name="toolTip">
880
- <string>The Cas endonuclease selected determines the gRNA
881
- search parameters</string>
882
- </property>
883
- <property name="text">
884
- <string>Endonuclease:</string>
885
- </property>
886
- </widget>
887
- </item>
888
- <item row="2" column="6">
889
- <widget class="QLineEdit" name="five_length">
890
- <property name="maximumSize">
891
- <size>
892
- <width>16777215</width>
893
- <height>16777215</height>
894
- </size>
895
- </property>
896
- <property name="readOnly">
897
- <bool>true</bool>
898
- </property>
899
- </widget>
900
- </item>
901
- <item row="2" column="5">
902
- <widget class="QLabel" name="label_3">
903
- <property name="sizePolicy">
904
- <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
905
- <horstretch>0</horstretch>
906
- <verstretch>0</verstretch>
907
- </sizepolicy>
908
- </property>
909
- <property name="toolTip">
910
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Length in nucleotides of gRNA sequence upstream (5')&lt;/p&gt;&lt;p&gt;of the seed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
911
- </property>
912
- <property name="text">
913
- <string>5' Length:</string>
914
- </property>
915
- </widget>
916
- </item>
917
- <item row="1" column="2">
918
- <widget class="QLineEdit" name="orgName">
919
- <property name="maximumSize">
920
- <size>
921
- <width>16777215</width>
922
- <height>16777215</height>
923
- </size>
924
- </property>
925
- </widget>
926
- </item>
927
- <item row="3" column="2">
928
- <widget class="QComboBox" name="comboBoxEndo">
929
- <property name="sizePolicy">
930
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
931
- <horstretch>0</horstretch>
932
- <verstretch>0</verstretch>
933
- </sizepolicy>
934
- </property>
935
- <property name="maximumSize">
936
- <size>
937
- <width>16777215</width>
938
- <height>16777215</height>
939
- </size>
940
- </property>
941
- </widget>
942
- </item>
943
- <item row="4" column="1">
944
- <widget class="QLabel" name="label">
945
- <property name="sizePolicy">
946
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
947
- <horstretch>0</horstretch>
948
- <verstretch>0</verstretch>
949
- </sizepolicy>
950
- </property>
951
- <property name="toolTip">
952
- <string>The organism code is the manner in which CASPER will label its data files
953
- and references for the organism you are importing here.</string>
954
- </property>
955
- <property name="text">
956
- <string>Organism Code:</string>
957
- </property>
958
- </widget>
959
- </item>
960
- <item row="3" column="0">
961
- <widget class="QLabel" name="label_13">
962
- <property name="text">
963
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
964
- </property>
965
- </widget>
966
- </item>
967
- <item row="1" column="1">
968
- <widget class="QLabel" name="OrganismName">
969
- <property name="sizePolicy">
970
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
971
- <horstretch>0</horstretch>
972
- <verstretch>0</verstretch>
973
- </sizepolicy>
974
- </property>
975
- <property name="text">
976
- <string>Organism Name:</string>
977
- </property>
978
- </widget>
979
- </item>
980
- <item row="5" column="1" colspan="6">
981
- <spacer name="verticalSpacer_4">
982
- <property name="orientation">
983
- <enum>Qt::Vertical</enum>
984
- </property>
985
- <property name="sizeType">
986
- <enum>QSizePolicy::Fixed</enum>
987
- </property>
988
- <property name="sizeHint" stdset="0">
989
- <size>
990
- <width>10</width>
991
- <height>10</height>
992
- </size>
993
- </property>
994
- </spacer>
995
- </item>
996
- <item row="0" column="1" colspan="6">
997
- <spacer name="verticalSpacer_3">
998
- <property name="orientation">
999
- <enum>Qt::Vertical</enum>
1000
- </property>
1001
- <property name="sizeType">
1002
- <enum>QSizePolicy::Fixed</enum>
1003
- </property>
1004
- <property name="sizeHint" stdset="0">
1005
- <size>
1006
- <width>10</width>
1007
- <height>10</height>
1008
- </size>
1009
- </property>
1010
- </spacer>
1011
- </item>
1012
- </layout>
1013
- </widget>
1014
- </item>
1015
- </layout>
1016
- </widget>
1017
- <widget class="QMenuBar" name="menubar">
1018
- <property name="geometry">
1019
- <rect>
1020
- <x>0</x>
1021
- <y>0</y>
1022
- <width>811</width>
1023
- <height>24</height>
1024
- </rect>
1025
- </property>
1026
- <widget class="QMenu" name="menu">
1027
- <property name="title">
1028
- <string>Help</string>
1029
- </property>
1030
- <addaction name="visit_repo"/>
1031
- <addaction name="go_ncbi"/>
1032
- </widget>
1033
- <widget class="QMenu" name="menuGenome">
1034
- <property name="title">
1035
- <string>Genome</string>
1036
- </property>
1037
- <addaction name="actionUpload_New_Endonuclease"/>
1038
- </widget>
1039
- <addaction name="menuGenome"/>
1040
- <addaction name="menu"/>
1041
- </widget>
1042
- <widget class="QStatusBar" name="statusbar"/>
1043
- <action name="visit_repo">
1044
- <property name="text">
1045
- <string>Visit Repository</string>
1046
- </property>
1047
- </action>
1048
- <action name="go_ncbi">
1049
- <property name="text">
1050
- <string>Go to NCBI</string>
1051
- </property>
1052
- </action>
1053
- <action name="actionUpload_New_Endonuclease">
1054
- <property name="text">
1055
- <string>Define New Endonuclease</string>
1056
- </property>
1057
- </action>
1058
- </widget>
1059
- <tabstops>
1060
- <tabstop>orgName</tabstop>
1061
- <tabstop>strainName</tabstop>
1062
- <tabstop>comboBoxEndo</tabstop>
1063
- <tabstop>orgCode</tabstop>
1064
- <tabstop>seed_length</tabstop>
1065
- <tabstop>five_length</tabstop>
1066
- <tabstop>three_length</tabstop>
1067
- <tabstop>repeats_box</tabstop>
1068
- <tabstop>mt</tabstop>
1069
- <tabstop>NCBI_File_Search</tabstop>
1070
- <tabstop>browseForFile</tabstop>
1071
- <tabstop>selectedFile</tabstop>
1072
- <tabstop>clearButton</tabstop>
1073
- <tabstop>remove_job</tabstop>
1074
- <tabstop>runButton</tabstop>
1075
- <tabstop>job_Table</tabstop>
1076
- <tabstop>output_browser</tabstop>
1077
- </tabstops>
1078
- <resources/>
1079
- <connections/>
1080
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/annotation_details.ui DELETED
@@ -1,376 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="enabled">
6
- <bool>true</bool>
7
- </property>
8
- <property name="geometry">
9
- <rect>
10
- <x>0</x>
11
- <y>0</y>
12
- <width>978</width>
13
- <height>600</height>
14
- </rect>
15
- </property>
16
- <property name="font">
17
- <font>
18
- <family>Arial</family>
19
- <pointsize>12</pointsize>
20
- <weight>50</weight>
21
- <italic>false</italic>
22
- <bold>false</bold>
23
- </font>
24
- </property>
25
- <property name="windowTitle">
26
- <string>CASPER</string>
27
- </property>
28
- <property name="styleSheet">
29
- <string notr="true"/>
30
- </property>
31
- <widget class="QWidget" name="centralwidget">
32
- <layout class="QGridLayout" name="gridLayout">
33
- <item row="8" column="1" colspan="4">
34
- <spacer name="verticalSpacer">
35
- <property name="orientation">
36
- <enum>Qt::Vertical</enum>
37
- </property>
38
- <property name="sizeType">
39
- <enum>QSizePolicy::Fixed</enum>
40
- </property>
41
- <property name="sizeHint" stdset="0">
42
- <size>
43
- <width>20</width>
44
- <height>20</height>
45
- </size>
46
- </property>
47
- </spacer>
48
- </item>
49
- <item row="4" column="1">
50
- <widget class="QCheckBox" name="select_all_checkbox">
51
- <property name="text">
52
- <string>Select All</string>
53
- </property>
54
- </widget>
55
- </item>
56
- <item row="7" column="6">
57
- <widget class="QLabel" name="label_2">
58
- <property name="minimumSize">
59
- <size>
60
- <width>50</width>
61
- <height>0</height>
62
- </size>
63
- </property>
64
- <property name="maximumSize">
65
- <size>
66
- <width>50</width>
67
- <height>16777215</height>
68
- </size>
69
- </property>
70
- <property name="text">
71
- <string/>
72
- </property>
73
- </widget>
74
- </item>
75
- <item row="1" column="4">
76
- <widget class="QLabel" name="label_7">
77
- <property name="font">
78
- <font>
79
- <family>Arial</family>
80
- <pointsize>12</pointsize>
81
- <weight>50</weight>
82
- <italic>false</italic>
83
- <bold>false</bold>
84
- </font>
85
- </property>
86
- <property name="styleSheet">
87
- <string notr="true"/>
88
- </property>
89
- <property name="text">
90
- <string>V2.0 (Beta) CRISPR Associated Software for Pathway Engineering and Research</string>
91
- </property>
92
- </widget>
93
- </item>
94
- <item row="5" column="6">
95
- <spacer name="horizontalSpacer_2">
96
- <property name="orientation">
97
- <enum>Qt::Horizontal</enum>
98
- </property>
99
- <property name="sizeType">
100
- <enum>QSizePolicy::Fixed</enum>
101
- </property>
102
- <property name="sizeHint" stdset="0">
103
- <size>
104
- <width>20</width>
105
- <height>20</height>
106
- </size>
107
- </property>
108
- </spacer>
109
- </item>
110
- <item row="1" column="1" colspan="3">
111
- <widget class="QLabel" name="label_8">
112
- <property name="sizePolicy">
113
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
114
- <horstretch>0</horstretch>
115
- <verstretch>0</verstretch>
116
- </sizepolicy>
117
- </property>
118
- <property name="maximumSize">
119
- <size>
120
- <width>16777215</width>
121
- <height>16777215</height>
122
- </size>
123
- </property>
124
- <property name="styleSheet">
125
- <string notr="true"/>
126
- </property>
127
- <property name="text">
128
- <string>CASPER</string>
129
- </property>
130
- </widget>
131
- </item>
132
- <item row="4" column="0">
133
- <widget class="QLabel" name="label">
134
- <property name="minimumSize">
135
- <size>
136
- <width>50</width>
137
- <height>0</height>
138
- </size>
139
- </property>
140
- <property name="maximumSize">
141
- <size>
142
- <width>50</width>
143
- <height>16777215</height>
144
- </size>
145
- </property>
146
- <property name="text">
147
- <string/>
148
- </property>
149
- </widget>
150
- </item>
151
- <item row="5" column="1" colspan="4">
152
- <widget class="QTableWidget" name="tableWidget">
153
- <property name="minimumSize">
154
- <size>
155
- <width>0</width>
156
- <height>317</height>
157
- </size>
158
- </property>
159
- <property name="maximumSize">
160
- <size>
161
- <width>16777215</width>
162
- <height>16777215</height>
163
- </size>
164
- </property>
165
- </widget>
166
- </item>
167
- <item row="0" column="1" colspan="4">
168
- <spacer name="verticalSpacer_2">
169
- <property name="orientation">
170
- <enum>Qt::Vertical</enum>
171
- </property>
172
- <property name="sizeType">
173
- <enum>QSizePolicy::Fixed</enum>
174
- </property>
175
- <property name="sizeHint" stdset="0">
176
- <size>
177
- <width>20</width>
178
- <height>20</height>
179
- </size>
180
- </property>
181
- </spacer>
182
- </item>
183
- <item row="5" column="0">
184
- <spacer name="horizontalSpacer">
185
- <property name="orientation">
186
- <enum>Qt::Horizontal</enum>
187
- </property>
188
- <property name="sizeType">
189
- <enum>QSizePolicy::Fixed</enum>
190
- </property>
191
- <property name="sizeHint" stdset="0">
192
- <size>
193
- <width>20</width>
194
- <height>20</height>
195
- </size>
196
- </property>
197
- </spacer>
198
- </item>
199
- <item row="2" column="1" colspan="4">
200
- <widget class="Line" name="line">
201
- <property name="orientation">
202
- <enum>Qt::Horizontal</enum>
203
- </property>
204
- </widget>
205
- </item>
206
- <item row="6" column="1" rowspan="2" colspan="4">
207
- <layout class="QHBoxLayout" name="horizontalLayout">
208
- <item alignment="Qt::AlignLeft">
209
- <widget class="QPushButton" name="Go_Back_Button">
210
- <property name="sizePolicy">
211
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
212
- <horstretch>0</horstretch>
213
- <verstretch>0</verstretch>
214
- </sizepolicy>
215
- </property>
216
- <property name="minimumSize">
217
- <size>
218
- <width>125</width>
219
- <height>0</height>
220
- </size>
221
- </property>
222
- <property name="maximumSize">
223
- <size>
224
- <width>16777215</width>
225
- <height>16777215</height>
226
- </size>
227
- </property>
228
- <property name="text">
229
- <string>Return</string>
230
- </property>
231
- </widget>
232
- </item>
233
- <item alignment="Qt::AlignRight">
234
- <widget class="QPushButton" name="Submit_button">
235
- <property name="sizePolicy">
236
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
237
- <horstretch>0</horstretch>
238
- <verstretch>0</verstretch>
239
- </sizepolicy>
240
- </property>
241
- <property name="minimumSize">
242
- <size>
243
- <width>125</width>
244
- <height>0</height>
245
- </size>
246
- </property>
247
- <property name="maximumSize">
248
- <size>
249
- <width>16777215</width>
250
- <height>16777215</height>
251
- </size>
252
- </property>
253
- <property name="text">
254
- <string>Submit</string>
255
- </property>
256
- </widget>
257
- </item>
258
- </layout>
259
- </item>
260
- </layout>
261
- </widget>
262
- <widget class="QStatusBar" name="statusbar"/>
263
- <action name="actionNew">
264
- <property name="text">
265
- <string>New</string>
266
- </property>
267
- </action>
268
- <action name="actionOpen">
269
- <property name="text">
270
- <string>Open</string>
271
- </property>
272
- </action>
273
- <action name="actionOpen_Recent">
274
- <property name="text">
275
- <string>Open Recent...</string>
276
- </property>
277
- </action>
278
- <action name="actionSave">
279
- <property name="text">
280
- <string>Save</string>
281
- </property>
282
- </action>
283
- <action name="actionExit">
284
- <property name="text">
285
- <string>Exit</string>
286
- </property>
287
- </action>
288
- <action name="actionUndo">
289
- <property name="text">
290
- <string>Undo</string>
291
- </property>
292
- </action>
293
- <action name="actionCut">
294
- <property name="text">
295
- <string>Cut</string>
296
- </property>
297
- </action>
298
- <action name="actionCopy">
299
- <property name="text">
300
- <string>Copy</string>
301
- </property>
302
- </action>
303
- <action name="actionPaste">
304
- <property name="text">
305
- <string>Paste</string>
306
- </property>
307
- </action>
308
- <action name="actionCut_Rev_Com">
309
- <property name="text">
310
- <string>Cut Rev-Com</string>
311
- </property>
312
- </action>
313
- <action name="actionCopy_Rev_Com">
314
- <property name="text">
315
- <string>Copy Rev-Com</string>
316
- </property>
317
- </action>
318
- <action name="actionPaste_Rev_Com">
319
- <property name="text">
320
- <string>Paste Rev-Com</string>
321
- </property>
322
- </action>
323
- <action name="actionUpload_New_Genome">
324
- <property name="text">
325
- <string>Seq_Finder Analysis...</string>
326
- </property>
327
- </action>
328
- <action name="actionUpload_New_Endonuclease">
329
- <property name="text">
330
- <string>Define New Endonuclease...</string>
331
- </property>
332
- </action>
333
- <action name="actionChange_Directory">
334
- <property name="text">
335
- <string>Change Database Directory</string>
336
- </property>
337
- </action>
338
- <action name="actionNCBI_BLAST">
339
- <property name="text">
340
- <string>NCBI BLAST</string>
341
- </property>
342
- </action>
343
- <action name="actionExcel_csv">
344
- <property name="text">
345
- <string>Excel (.csv)</string>
346
- </property>
347
- </action>
348
- <action name="actionIDT_Order">
349
- <property name="text">
350
- <string>IDT Order</string>
351
- </property>
352
- </action>
353
- <action name="actionMultitargeting">
354
- <property name="text">
355
- <string>Multitargeting</string>
356
- </property>
357
- </action>
358
- <action name="actionPopulation_Analysis">
359
- <property name="text">
360
- <string>Population Analysis</string>
361
- </property>
362
- </action>
363
- <action name="actionComplete_Target_Analysis">
364
- <property name="text">
365
- <string>Complete Target Analysis</string>
366
- </property>
367
- </action>
368
- <action name="actionNew_CASPER_Window">
369
- <property name="text">
370
- <string>New CASPER Window</string>
371
- </property>
372
- </action>
373
- </widget>
374
- <resources/>
375
- <connections/>
376
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/closing_window.ui DELETED
@@ -1,136 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>400</width>
10
- <height>300</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="1" column="0">
24
- <spacer name="horizontalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Horizontal</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="1">
40
- <layout class="QGridLayout" name="gridLayout">
41
- <item row="0" column="0">
42
- <widget class="QLabel" name="label">
43
- <property name="sizePolicy">
44
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
45
- <horstretch>0</horstretch>
46
- <verstretch>0</verstretch>
47
- </sizepolicy>
48
- </property>
49
- <property name="text">
50
- <string>Would you like to delete any files?</string>
51
- </property>
52
- <property name="alignment">
53
- <set>Qt::AlignCenter</set>
54
- </property>
55
- </widget>
56
- </item>
57
- <item row="1" column="0">
58
- <widget class="QTableWidget" name="files_table">
59
- <property name="toolTip">
60
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This table has all of the files in your CSPR database folder.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Please select/highlight which files you would like deleted upon closure of this program.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
61
- </property>
62
- </widget>
63
- </item>
64
- <item row="2" column="0">
65
- <widget class="QPushButton" name="submit_button">
66
- <property name="sizePolicy">
67
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
68
- <horstretch>0</horstretch>
69
- <verstretch>0</verstretch>
70
- </sizepolicy>
71
- </property>
72
- <property name="toolTip">
73
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Once pressed, this button will delete any and all selected/highlighted files in the table.&lt;/p&gt;&lt;p&gt;If no files are selected/highlighted, no files will be deleted.&lt;/p&gt;&lt;p&gt;After this process is done, the program will close.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
74
- </property>
75
- <property name="text">
76
- <string>Submit</string>
77
- </property>
78
- </widget>
79
- </item>
80
- </layout>
81
- </item>
82
- <item row="1" column="2">
83
- <spacer name="horizontalSpacer_2">
84
- <property name="orientation">
85
- <enum>Qt::Horizontal</enum>
86
- </property>
87
- <property name="sizeType">
88
- <enum>QSizePolicy::Fixed</enum>
89
- </property>
90
- <property name="sizeHint" stdset="0">
91
- <size>
92
- <width>20</width>
93
- <height>20</height>
94
- </size>
95
- </property>
96
- </spacer>
97
- </item>
98
- <item row="2" column="1">
99
- <spacer name="verticalSpacer">
100
- <property name="orientation">
101
- <enum>Qt::Vertical</enum>
102
- </property>
103
- <property name="sizeType">
104
- <enum>QSizePolicy::Fixed</enum>
105
- </property>
106
- <property name="sizeHint" stdset="0">
107
- <size>
108
- <width>20</width>
109
- <height>20</height>
110
- </size>
111
- </property>
112
- </spacer>
113
- </item>
114
- <item row="0" column="1">
115
- <spacer name="verticalSpacer_2">
116
- <property name="orientation">
117
- <enum>Qt::Vertical</enum>
118
- </property>
119
- <property name="sizeType">
120
- <enum>QSizePolicy::Fixed</enum>
121
- </property>
122
- <property name="sizeHint" stdset="0">
123
- <size>
124
- <width>20</width>
125
- <height>20</height>
126
- </size>
127
- </property>
128
- </spacer>
129
- </item>
130
- </layout>
131
- </widget>
132
- <widget class="QStatusBar" name="statusbar"/>
133
- </widget>
134
- <resources/>
135
- <connections/>
136
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/cotargeting.ui DELETED
@@ -1,173 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>450</width>
10
- <height>375</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="1" column="0">
24
- <spacer name="horizontalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Horizontal</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="1">
40
- <layout class="QGridLayout" name="gridLayout">
41
- <item row="2" column="0">
42
- <widget class="QLabel" name="label">
43
- <property name="sizePolicy">
44
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
45
- <horstretch>0</horstretch>
46
- <verstretch>0</verstretch>
47
- </sizepolicy>
48
- </property>
49
- <property name="text">
50
- <string>Organism:</string>
51
- </property>
52
- </widget>
53
- </item>
54
- <item row="1" column="0" colspan="2">
55
- <widget class="Line" name="line">
56
- <property name="orientation">
57
- <enum>Qt::Horizontal</enum>
58
- </property>
59
- </widget>
60
- </item>
61
- <item row="4" column="0" alignment="Qt::AlignLeft">
62
- <widget class="QPushButton" name="cancel_button">
63
- <property name="minimumSize">
64
- <size>
65
- <width>125</width>
66
- <height>0</height>
67
- </size>
68
- </property>
69
- <property name="toolTip">
70
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Cancel button. Cancels everything, and closes out of this window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
71
- </property>
72
- <property name="text">
73
- <string>Cancel</string>
74
- </property>
75
- </widget>
76
- </item>
77
- <item row="0" column="0">
78
- <widget class="QLabel" name="title">
79
- <property name="text">
80
- <string>Co-Targeting</string>
81
- </property>
82
- </widget>
83
- </item>
84
- <item row="3" column="0" colspan="2">
85
- <widget class="QTableWidget" name="endo_table">
86
- <property name="toolTip">
87
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;These are the list of endonucleases available for this organism. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Select which endonucleases you want shown at the same time.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
88
- </property>
89
- </widget>
90
- </item>
91
- <item row="2" column="1">
92
- <widget class="QLineEdit" name="orgName">
93
- <property name="enabled">
94
- <bool>false</bool>
95
- </property>
96
- <property name="toolTip">
97
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This is the organism that targets have been searched for.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
98
- </property>
99
- </widget>
100
- </item>
101
- <item row="4" column="1" alignment="Qt::AlignRight">
102
- <widget class="QPushButton" name="submit_button">
103
- <property name="minimumSize">
104
- <size>
105
- <width>125</width>
106
- <height>0</height>
107
- </size>
108
- </property>
109
- <property name="toolTip">
110
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Submit button. &lt;br/&gt;Takes the endonucleases selected, and shows them in the same table in the resutls window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
111
- </property>
112
- <property name="text">
113
- <string>Submit</string>
114
- </property>
115
- </widget>
116
- </item>
117
- </layout>
118
- </item>
119
- <item row="1" column="2">
120
- <spacer name="horizontalSpacer_2">
121
- <property name="orientation">
122
- <enum>Qt::Horizontal</enum>
123
- </property>
124
- <property name="sizeType">
125
- <enum>QSizePolicy::Fixed</enum>
126
- </property>
127
- <property name="sizeHint" stdset="0">
128
- <size>
129
- <width>20</width>
130
- <height>20</height>
131
- </size>
132
- </property>
133
- </spacer>
134
- </item>
135
- <item row="2" column="1">
136
- <spacer name="verticalSpacer">
137
- <property name="orientation">
138
- <enum>Qt::Vertical</enum>
139
- </property>
140
- <property name="sizeType">
141
- <enum>QSizePolicy::Fixed</enum>
142
- </property>
143
- <property name="sizeHint" stdset="0">
144
- <size>
145
- <width>20</width>
146
- <height>20</height>
147
- </size>
148
- </property>
149
- </spacer>
150
- </item>
151
- <item row="0" column="1">
152
- <spacer name="verticalSpacer_2">
153
- <property name="orientation">
154
- <enum>Qt::Vertical</enum>
155
- </property>
156
- <property name="sizeType">
157
- <enum>QSizePolicy::Fixed</enum>
158
- </property>
159
- <property name="sizeHint" stdset="0">
160
- <size>
161
- <width>20</width>
162
- <height>20</height>
163
- </size>
164
- </property>
165
- </spacer>
166
- </item>
167
- </layout>
168
- </widget>
169
- <widget class="QStatusBar" name="statusbar"/>
170
- </widget>
171
- <resources/>
172
- <connections/>
173
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/export_tool.ui DELETED
@@ -1,264 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>590</width>
10
- <height>345</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="2" column="1" colspan="2">
24
- <widget class="QGroupBox" name="gRNA_Options">
25
- <property name="title">
26
- <string>Guide Options</string>
27
- </property>
28
- <layout class="QGridLayout" name="gridLayout_6">
29
- <item row="1" column="0">
30
- <widget class="QLabel" name="label_3">
31
- <property name="text">
32
- <string>5' Leading Sequence:</string>
33
- </property>
34
- </widget>
35
- </item>
36
- <item row="1" column="1">
37
- <widget class="QLineEdit" name="leading_seq">
38
- <property name="placeholderText">
39
- <string>E.g. promoter, tRNA, homology overhang, etc.</string>
40
- </property>
41
- </widget>
42
- </item>
43
- <item row="2" column="1">
44
- <widget class="QLineEdit" name="trailing_seq">
45
- <property name="placeholderText">
46
- <string>E.g. gRNA scaffold, terminator, etc.</string>
47
- </property>
48
- </widget>
49
- </item>
50
- <item row="2" column="0">
51
- <widget class="QLabel" name="label_4">
52
- <property name="text">
53
- <string>3' Trailing Sequence:</string>
54
- </property>
55
- </widget>
56
- </item>
57
- </layout>
58
- </widget>
59
- </item>
60
- <item row="1" column="1" colspan="2">
61
- <widget class="QGroupBox" name="export_Options">
62
- <property name="title">
63
- <string>Export Options</string>
64
- </property>
65
- <layout class="QGridLayout" name="gridLayout_3">
66
- <item row="0" column="0">
67
- <widget class="QLabel" name="label">
68
- <property name="text">
69
- <string>File Location:</string>
70
- </property>
71
- </widget>
72
- </item>
73
- <item row="1" column="0">
74
- <widget class="QLabel" name="label_2">
75
- <property name="sizePolicy">
76
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
77
- <horstretch>0</horstretch>
78
- <verstretch>0</verstretch>
79
- </sizepolicy>
80
- </property>
81
- <property name="text">
82
- <string>File Name:</string>
83
- </property>
84
- </widget>
85
- </item>
86
- <item row="1" column="2">
87
- <widget class="QLabel" name="label_5">
88
- <property name="text">
89
- <string>Delimiter:</string>
90
- </property>
91
- </widget>
92
- </item>
93
- <item row="1" column="1">
94
- <widget class="QLineEdit" name="filename_line_edit">
95
- <property name="toolTip">
96
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Please write the file name you want.&lt;/p&gt;&lt;p&gt;Note: it is not necessary to add the file extension.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
97
- </property>
98
- <property name="placeholderText">
99
- <string>Enter file name</string>
100
- </property>
101
- </widget>
102
- </item>
103
- <item row="1" column="3">
104
- <widget class="QComboBox" name="delimBox">
105
- <item>
106
- <property name="text">
107
- <string>,</string>
108
- </property>
109
- </item>
110
- <item>
111
- <property name="text">
112
- <string>\t</string>
113
- </property>
114
- </item>
115
- <item>
116
- <property name="text">
117
- <string>;</string>
118
- </property>
119
- </item>
120
- <item>
121
- <property name="text">
122
- <string>:</string>
123
- </property>
124
- </item>
125
- </widget>
126
- </item>
127
- <item row="0" column="3">
128
- <widget class="QPushButton" name="browse_button">
129
- <property name="sizePolicy">
130
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
131
- <horstretch>0</horstretch>
132
- <verstretch>0</verstretch>
133
- </sizepolicy>
134
- </property>
135
- <property name="toolTip">
136
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Browse for a folder to store the CSV file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
137
- </property>
138
- <property name="text">
139
- <string>Browse</string>
140
- </property>
141
- </widget>
142
- </item>
143
- <item row="0" column="1" colspan="2">
144
- <widget class="QLineEdit" name="fileLocation_line_edit">
145
- <property name="readOnly">
146
- <bool>true</bool>
147
- </property>
148
- <property name="placeholderText">
149
- <string>Select directory</string>
150
- </property>
151
- </widget>
152
- </item>
153
- </layout>
154
- </widget>
155
- </item>
156
- <item row="3" column="2" alignment="Qt::AlignRight">
157
- <widget class="QPushButton" name="export_button">
158
- <property name="sizePolicy">
159
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
160
- <horstretch>0</horstretch>
161
- <verstretch>0</verstretch>
162
- </sizepolicy>
163
- </property>
164
- <property name="minimumSize">
165
- <size>
166
- <width>125</width>
167
- <height>0</height>
168
- </size>
169
- </property>
170
- <property name="text">
171
- <string>Export</string>
172
- </property>
173
- </widget>
174
- </item>
175
- <item row="3" column="1" alignment="Qt::AlignLeft">
176
- <widget class="QPushButton" name="cancel_button">
177
- <property name="sizePolicy">
178
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
179
- <horstretch>0</horstretch>
180
- <verstretch>0</verstretch>
181
- </sizepolicy>
182
- </property>
183
- <property name="minimumSize">
184
- <size>
185
- <width>125</width>
186
- <height>0</height>
187
- </size>
188
- </property>
189
- <property name="text">
190
- <string>Cancel</string>
191
- </property>
192
- </widget>
193
- </item>
194
- <item row="1" column="3" rowspan="2">
195
- <spacer name="horizontalSpacer_3">
196
- <property name="orientation">
197
- <enum>Qt::Horizontal</enum>
198
- </property>
199
- <property name="sizeType">
200
- <enum>QSizePolicy::Fixed</enum>
201
- </property>
202
- <property name="sizeHint" stdset="0">
203
- <size>
204
- <width>20</width>
205
- <height>20</height>
206
- </size>
207
- </property>
208
- </spacer>
209
- </item>
210
- <item row="1" column="0" rowspan="2">
211
- <spacer name="horizontalSpacer_2">
212
- <property name="orientation">
213
- <enum>Qt::Horizontal</enum>
214
- </property>
215
- <property name="sizeType">
216
- <enum>QSizePolicy::Fixed</enum>
217
- </property>
218
- <property name="sizeHint" stdset="0">
219
- <size>
220
- <width>20</width>
221
- <height>20</height>
222
- </size>
223
- </property>
224
- </spacer>
225
- </item>
226
- <item row="0" column="1" colspan="2">
227
- <spacer name="verticalSpacer_2">
228
- <property name="orientation">
229
- <enum>Qt::Vertical</enum>
230
- </property>
231
- <property name="sizeType">
232
- <enum>QSizePolicy::Fixed</enum>
233
- </property>
234
- <property name="sizeHint" stdset="0">
235
- <size>
236
- <width>20</width>
237
- <height>20</height>
238
- </size>
239
- </property>
240
- </spacer>
241
- </item>
242
- <item row="5" column="1" colspan="2">
243
- <spacer name="verticalSpacer">
244
- <property name="orientation">
245
- <enum>Qt::Vertical</enum>
246
- </property>
247
- <property name="sizeType">
248
- <enum>QSizePolicy::Fixed</enum>
249
- </property>
250
- <property name="sizeHint" stdset="0">
251
- <size>
252
- <width>20</width>
253
- <height>20</height>
254
- </size>
255
- </property>
256
- </spacer>
257
- </item>
258
- </layout>
259
- </widget>
260
- <widget class="QStatusBar" name="statusbar"/>
261
- </widget>
262
- <resources/>
263
- <connections/>
264
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/filter_options.ui DELETED
@@ -1,223 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>352</width>
10
- <height>297</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="1" column="1" rowspan="2">
24
- <widget class="QGroupBox" name="filterBox">
25
- <property name="title">
26
- <string/>
27
- </property>
28
- <layout class="QGridLayout" name="gridLayout_3">
29
- <item row="0" column="0">
30
- <layout class="QGridLayout" name="gridLayout">
31
- <item row="4" column="1">
32
- <widget class="QLineEdit" name="minScoreLine">
33
- <property name="enabled">
34
- <bool>false</bool>
35
- </property>
36
- <property name="sizePolicy">
37
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
38
- <horstretch>0</horstretch>
39
- <verstretch>0</verstretch>
40
- </sizepolicy>
41
- </property>
42
- </widget>
43
- </item>
44
- <item row="1" column="0" colspan="2">
45
- <widget class="Line" name="line">
46
- <property name="orientation">
47
- <enum>Qt::Horizontal</enum>
48
- </property>
49
- </widget>
50
- </item>
51
- <item row="3" column="1">
52
- <widget class="QCheckBox" name="cotarget_checkbox">
53
- <property name="enabled">
54
- <bool>false</bool>
55
- </property>
56
- <property name="sizePolicy">
57
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
58
- <horstretch>0</horstretch>
59
- <verstretch>0</verstretch>
60
- </sizepolicy>
61
- </property>
62
- <property name="text">
63
- <string/>
64
- </property>
65
- </widget>
66
- </item>
67
- <item row="2" column="1">
68
- <widget class="QCheckBox" name="fivegseqCheckBox">
69
- <property name="sizePolicy">
70
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
71
- <horstretch>0</horstretch>
72
- <verstretch>0</verstretch>
73
- </sizepolicy>
74
- </property>
75
- <property name="text">
76
- <string/>
77
- </property>
78
- </widget>
79
- </item>
80
- <item row="4" column="0">
81
- <widget class="QLabel" name="label_3">
82
- <property name="sizePolicy">
83
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
84
- <horstretch>0</horstretch>
85
- <verstretch>0</verstretch>
86
- </sizepolicy>
87
- </property>
88
- <property name="toolTip">
89
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Filter guides based on minimum desired on-target score.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
90
- </property>
91
- <property name="text">
92
- <string>Minimum On-Target Score</string>
93
- </property>
94
- </widget>
95
- </item>
96
- <item row="3" column="0">
97
- <widget class="QLabel" name="label_2">
98
- <property name="sizePolicy">
99
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
100
- <horstretch>0</horstretch>
101
- <verstretch>0</verstretch>
102
- </sizepolicy>
103
- </property>
104
- <property name="toolTip">
105
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Cotargeting must already have been run to use this option. Filters out guides that don't have multi-endonuclease targeting capabilities.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
106
- </property>
107
- <property name="text">
108
- <string>View Co-Targets Only</string>
109
- </property>
110
- </widget>
111
- </item>
112
- <item row="2" column="0">
113
- <widget class="QLabel" name="label">
114
- <property name="sizePolicy">
115
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
116
- <horstretch>0</horstretch>
117
- <verstretch>0</verstretch>
118
- </sizepolicy>
119
- </property>
120
- <property name="toolTip">
121
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Filters for guides containing a G residue at their 5' end. This may be useful for optimizing guide expression under some promoters.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
122
- </property>
123
- <property name="text">
124
- <string>View 5' G Sequences Only</string>
125
- </property>
126
- </widget>
127
- </item>
128
- <item row="0" column="0" colspan="2">
129
- <widget class="QLabel" name="title">
130
- <property name="sizePolicy">
131
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
132
- <horstretch>0</horstretch>
133
- <verstretch>0</verstretch>
134
- </sizepolicy>
135
- </property>
136
- <property name="text">
137
- <string>Filter Options</string>
138
- </property>
139
- </widget>
140
- </item>
141
- <item row="5" column="0" colspan="2">
142
- <widget class="QSlider" name="scoreSlider">
143
- <property name="orientation">
144
- <enum>Qt::Horizontal</enum>
145
- </property>
146
- </widget>
147
- </item>
148
- </layout>
149
- </item>
150
- </layout>
151
- </widget>
152
- </item>
153
- <item row="3" column="1">
154
- <spacer name="verticalSpacer">
155
- <property name="orientation">
156
- <enum>Qt::Vertical</enum>
157
- </property>
158
- <property name="sizeType">
159
- <enum>QSizePolicy::Fixed</enum>
160
- </property>
161
- <property name="sizeHint" stdset="0">
162
- <size>
163
- <width>20</width>
164
- <height>20</height>
165
- </size>
166
- </property>
167
- </spacer>
168
- </item>
169
- <item row="0" column="1">
170
- <spacer name="verticalSpacer_2">
171
- <property name="orientation">
172
- <enum>Qt::Vertical</enum>
173
- </property>
174
- <property name="sizeType">
175
- <enum>QSizePolicy::Fixed</enum>
176
- </property>
177
- <property name="sizeHint" stdset="0">
178
- <size>
179
- <width>20</width>
180
- <height>20</height>
181
- </size>
182
- </property>
183
- </spacer>
184
- </item>
185
- <item row="1" column="0">
186
- <spacer name="horizontalSpacer">
187
- <property name="orientation">
188
- <enum>Qt::Horizontal</enum>
189
- </property>
190
- <property name="sizeType">
191
- <enum>QSizePolicy::Fixed</enum>
192
- </property>
193
- <property name="sizeHint" stdset="0">
194
- <size>
195
- <width>20</width>
196
- <height>20</height>
197
- </size>
198
- </property>
199
- </spacer>
200
- </item>
201
- <item row="1" column="2">
202
- <spacer name="horizontalSpacer_2">
203
- <property name="orientation">
204
- <enum>Qt::Horizontal</enum>
205
- </property>
206
- <property name="sizeType">
207
- <enum>QSizePolicy::Fixed</enum>
208
- </property>
209
- <property name="sizeHint" stdset="0">
210
- <size>
211
- <width>20</width>
212
- <height>20</height>
213
- </size>
214
- </property>
215
- </spacer>
216
- </item>
217
- </layout>
218
- </widget>
219
- <widget class="QStatusBar" name="statusbar"/>
220
- </widget>
221
- <resources/>
222
- <connections/>
223
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/generate_library.ui DELETED
@@ -1,731 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>991</width>
10
- <height>518</height>
11
- </rect>
12
- </property>
13
- <property name="windowTitle">
14
- <string>MainWindow</string>
15
- </property>
16
- <widget class="QWidget" name="centralwidget">
17
- <layout class="QGridLayout" name="gridLayout_2">
18
- <item row="1" column="1">
19
- <layout class="QGridLayout" name="gridLayout" rowstretch="1,0,0,0,0" columnstretch="1,0">
20
- <property name="sizeConstraint">
21
- <enum>QLayout::SetDefaultConstraint</enum>
22
- </property>
23
- <item row="4" column="1" alignment="Qt::AlignRight">
24
- <widget class="QPushButton" name="submit_button">
25
- <property name="sizePolicy">
26
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
27
- <horstretch>0</horstretch>
28
- <verstretch>0</verstretch>
29
- </sizepolicy>
30
- </property>
31
- <property name="minimumSize">
32
- <size>
33
- <width>125</width>
34
- <height>0</height>
35
- </size>
36
- </property>
37
- <property name="text">
38
- <string>Submit</string>
39
- </property>
40
- </widget>
41
- </item>
42
- <item row="3" column="1">
43
- <widget class="QGroupBox" name="Step4">
44
- <property name="sizePolicy">
45
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
46
- <horstretch>0</horstretch>
47
- <verstretch>0</verstretch>
48
- </sizepolicy>
49
- </property>
50
- <property name="title">
51
- <string>Step 4: Output Location</string>
52
- </property>
53
- <layout class="QGridLayout" name="gridLayout_7" rowstretch="0,0,0,0">
54
- <item row="2" column="2">
55
- <widget class="QPushButton" name="BrowseButton">
56
- <property name="sizePolicy">
57
- <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
58
- <horstretch>0</horstretch>
59
- <verstretch>0</verstretch>
60
- </sizepolicy>
61
- </property>
62
- <property name="toolTip">
63
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Browse for a location to save your library!&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
64
- </property>
65
- <property name="text">
66
- <string>Browse</string>
67
- </property>
68
- </widget>
69
- </item>
70
- <item row="3" column="0" colspan="3">
71
- <spacer name="verticalSpacer_9">
72
- <property name="orientation">
73
- <enum>Qt::Vertical</enum>
74
- </property>
75
- <property name="sizeType">
76
- <enum>QSizePolicy::Fixed</enum>
77
- </property>
78
- <property name="sizeHint" stdset="0">
79
- <size>
80
- <width>10</width>
81
- <height>10</height>
82
- </size>
83
- </property>
84
- </spacer>
85
- </item>
86
- <item row="2" column="0">
87
- <widget class="QLabel" name="label_14">
88
- <property name="sizePolicy">
89
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
90
- <horstretch>0</horstretch>
91
- <verstretch>0</verstretch>
92
- </sizepolicy>
93
- </property>
94
- <property name="toolTip">
95
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;This is the directory that CASPER will write the library CSV to.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
96
- </property>
97
- <property name="text">
98
- <string>Output path:</string>
99
- </property>
100
- </widget>
101
- </item>
102
- <item row="1" column="0">
103
- <widget class="QLabel" name="label_13">
104
- <property name="sizePolicy">
105
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
106
- <horstretch>0</horstretch>
107
- <verstretch>0</verstretch>
108
- </sizepolicy>
109
- </property>
110
- <property name="toolTip">
111
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Name of generated CSV file.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
112
- </property>
113
- <property name="text">
114
- <string>Output file name:</string>
115
- </property>
116
- </widget>
117
- </item>
118
- <item row="1" column="1" colspan="2">
119
- <widget class="QLineEdit" name="filename_input">
120
- <property name="sizePolicy">
121
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
122
- <horstretch>0</horstretch>
123
- <verstretch>0</verstretch>
124
- </sizepolicy>
125
- </property>
126
- </widget>
127
- </item>
128
- <item row="2" column="1">
129
- <widget class="QLineEdit" name="output_path">
130
- <property name="sizePolicy">
131
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
132
- <horstretch>0</horstretch>
133
- <verstretch>0</verstretch>
134
- </sizepolicy>
135
- </property>
136
- </widget>
137
- </item>
138
- <item row="0" column="0" colspan="3">
139
- <spacer name="verticalSpacer_10">
140
- <property name="orientation">
141
- <enum>Qt::Vertical</enum>
142
- </property>
143
- <property name="sizeType">
144
- <enum>QSizePolicy::Fixed</enum>
145
- </property>
146
- <property name="sizeHint" stdset="0">
147
- <size>
148
- <width>10</width>
149
- <height>10</height>
150
- </size>
151
- </property>
152
- </spacer>
153
- </item>
154
- </layout>
155
- </widget>
156
- </item>
157
- <item row="4" column="0" alignment="Qt::AlignLeft">
158
- <widget class="QPushButton" name="cancel_button">
159
- <property name="sizePolicy">
160
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
161
- <horstretch>0</horstretch>
162
- <verstretch>0</verstretch>
163
- </sizepolicy>
164
- </property>
165
- <property name="minimumSize">
166
- <size>
167
- <width>125</width>
168
- <height>0</height>
169
- </size>
170
- </property>
171
- <property name="toolTip">
172
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Cancel button, clears everything and closes the window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
173
- </property>
174
- <property name="text">
175
- <string>Cancel</string>
176
- </property>
177
- </widget>
178
- </item>
179
- <item row="1" column="0" colspan="2">
180
- <widget class="Line" name="line">
181
- <property name="sizePolicy">
182
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
183
- <horstretch>0</horstretch>
184
- <verstretch>0</verstretch>
185
- </sizepolicy>
186
- </property>
187
- <property name="orientation">
188
- <enum>Qt::Horizontal</enum>
189
- </property>
190
- </widget>
191
- </item>
192
- <item row="2" column="1">
193
- <widget class="QGroupBox" name="Step3">
194
- <property name="sizePolicy">
195
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
196
- <horstretch>0</horstretch>
197
- <verstretch>0</verstretch>
198
- </sizepolicy>
199
- </property>
200
- <property name="title">
201
- <string>Step 3: Targeting Guidelines</string>
202
- </property>
203
- <layout class="QGridLayout" name="gridLayout_8" rowstretch="0,0,0,0,0">
204
- <property name="sizeConstraint">
205
- <enum>QLayout::SetDefaultConstraint</enum>
206
- </property>
207
- <item row="3" column="1">
208
- <widget class="QCheckBox" name="modifyParamscheckBox">
209
- <property name="sizePolicy">
210
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
211
- <horstretch>0</horstretch>
212
- <verstretch>0</verstretch>
213
- </sizepolicy>
214
- </property>
215
- <property name="text">
216
- <string/>
217
- </property>
218
- </widget>
219
- </item>
220
- <item row="1" column="0">
221
- <widget class="QLabel" name="label_10">
222
- <property name="sizePolicy">
223
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
224
- <horstretch>0</horstretch>
225
- <verstretch>0</verstretch>
226
- </sizepolicy>
227
- </property>
228
- <property name="toolTip">
229
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;This is the minimum distance in nt there must be between each guide in the library.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
230
- </property>
231
- <property name="text">
232
- <string>Space between guides:</string>
233
- </property>
234
- </widget>
235
- </item>
236
- <item row="2" column="1">
237
- <widget class="QLineEdit" name="fiveprimeseq">
238
- <property name="sizePolicy">
239
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
240
- <horstretch>0</horstretch>
241
- <verstretch>0</verstretch>
242
- </sizepolicy>
243
- </property>
244
- <property name="placeholderText">
245
- <string>Ex: G</string>
246
- </property>
247
- </widget>
248
- </item>
249
- <item row="1" column="1">
250
- <widget class="QLineEdit" name="space_line_edit">
251
- <property name="sizePolicy">
252
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
253
- <horstretch>0</horstretch>
254
- <verstretch>0</verstretch>
255
- </sizepolicy>
256
- </property>
257
- <property name="text">
258
- <string>15</string>
259
- </property>
260
- </widget>
261
- </item>
262
- <item row="0" column="0" colspan="2">
263
- <spacer name="verticalSpacer_7">
264
- <property name="orientation">
265
- <enum>Qt::Vertical</enum>
266
- </property>
267
- <property name="sizeType">
268
- <enum>QSizePolicy::Fixed</enum>
269
- </property>
270
- <property name="sizeHint" stdset="0">
271
- <size>
272
- <width>10</width>
273
- <height>10</height>
274
- </size>
275
- </property>
276
- </spacer>
277
- </item>
278
- <item row="2" column="0">
279
- <widget class="QLabel" name="label_11">
280
- <property name="sizePolicy">
281
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
282
- <horstretch>0</horstretch>
283
- <verstretch>0</verstretch>
284
- </sizepolicy>
285
- </property>
286
- <property name="toolTip">
287
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This specifies the 5' characters of the guides. &lt;span style=&quot; font-weight:600;&quot;&gt;For example&lt;/span&gt;, to optimize gRNA expression under some promoters, 5' G residues are needed. Typing &amp;quot;G&amp;quot; in the box returns only guides starting with G. Input must be &amp;quot;ACGT&amp;quot; alphabet. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
288
- </property>
289
- <property name="text">
290
- <string>5' end specificity:</string>
291
- </property>
292
- </widget>
293
- </item>
294
- <item row="3" column="0">
295
- <widget class="QLabel" name="label_12">
296
- <property name="sizePolicy">
297
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
298
- <horstretch>0</horstretch>
299
- <verstretch>0</verstretch>
300
- </sizepolicy>
301
- </property>
302
- <property name="toolTip">
303
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If CASPER is unable to find the selected nubmer of guides per gene given the selected criteria, it will loosen its criteria to achieve the selected number. Asterisks are used to denote guides with modified parameters.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
304
- </property>
305
- <property name="text">
306
- <string>Modify parameters if no target found:</string>
307
- </property>
308
- </widget>
309
- </item>
310
- <item row="4" column="0" colspan="2">
311
- <spacer name="verticalSpacer_8">
312
- <property name="orientation">
313
- <enum>Qt::Vertical</enum>
314
- </property>
315
- <property name="sizeType">
316
- <enum>QSizePolicy::Fixed</enum>
317
- </property>
318
- <property name="sizeHint" stdset="0">
319
- <size>
320
- <width>10</width>
321
- <height>10</height>
322
- </size>
323
- </property>
324
- </spacer>
325
- </item>
326
- </layout>
327
- </widget>
328
- </item>
329
- <item row="0" column="0" colspan="2">
330
- <widget class="QLabel" name="label">
331
- <property name="sizePolicy">
332
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
333
- <horstretch>0</horstretch>
334
- <verstretch>0</verstretch>
335
- </sizepolicy>
336
- </property>
337
- <property name="text">
338
- <string>Generate Library</string>
339
- </property>
340
- </widget>
341
- </item>
342
- <item row="3" column="0">
343
- <widget class="QGroupBox" name="Step2">
344
- <property name="sizePolicy">
345
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
346
- <horstretch>0</horstretch>
347
- <verstretch>0</verstretch>
348
- </sizepolicy>
349
- </property>
350
- <property name="title">
351
- <string>Step 2: Quality Filtering</string>
352
- </property>
353
- <layout class="QGridLayout" name="gridLayout_9" rowstretch="0,0,0,0,0,0" columnstretch="0,0">
354
- <item row="1" column="0">
355
- <widget class="QLabel" name="label_6">
356
- <property name="sizePolicy">
357
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
358
- <horstretch>0</horstretch>
359
- <verstretch>0</verstretch>
360
- </sizepolicy>
361
- </property>
362
- <property name="toolTip">
363
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Selecting this option performs off-target analysis within the organism. Range is from 0 to 0.5, &lt;span style=&quot; font-weight:600;&quot;&gt;lower is better&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
364
- </property>
365
- <property name="text">
366
- <string>Find off-targets:</string>
367
- </property>
368
- </widget>
369
- </item>
370
- <item row="0" column="0" colspan="2">
371
- <spacer name="verticalSpacer_5">
372
- <property name="orientation">
373
- <enum>Qt::Vertical</enum>
374
- </property>
375
- <property name="sizeType">
376
- <enum>QSizePolicy::Fixed</enum>
377
- </property>
378
- <property name="sizeHint" stdset="0">
379
- <size>
380
- <width>10</width>
381
- <height>10</height>
382
- </size>
383
- </property>
384
- </spacer>
385
- </item>
386
- <item row="4" column="1">
387
- <widget class="QProgressBar" name="progressBar">
388
- <property name="sizePolicy">
389
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
390
- <horstretch>0</horstretch>
391
- <verstretch>0</verstretch>
392
- </sizepolicy>
393
- </property>
394
- <property name="value">
395
- <number>0</number>
396
- </property>
397
- </widget>
398
- </item>
399
- <item row="1" column="1">
400
- <widget class="QCheckBox" name="find_off_Checkbox">
401
- <property name="sizePolicy">
402
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
403
- <horstretch>0</horstretch>
404
- <verstretch>0</verstretch>
405
- </sizepolicy>
406
- </property>
407
- <property name="text">
408
- <string/>
409
- </property>
410
- </widget>
411
- </item>
412
- <item row="2" column="1">
413
- <widget class="QComboBox" name="minON_comboBox">
414
- <property name="sizePolicy">
415
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
416
- <horstretch>0</horstretch>
417
- <verstretch>0</verstretch>
418
- </sizepolicy>
419
- </property>
420
- </widget>
421
- </item>
422
- <item row="2" column="0">
423
- <widget class="QLabel" name="label_7">
424
- <property name="sizePolicy">
425
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
426
- <horstretch>0</horstretch>
427
- <verstretch>0</verstretch>
428
- </sizepolicy>
429
- </property>
430
- <property name="toolTip">
431
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The minimum acceptable on-target score for guides in library. Range: 20-70, &lt;span style=&quot; font-weight:600;&quot;&gt;higher is better&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
432
- </property>
433
- <property name="text">
434
- <string>Minimum on-target score:</string>
435
- </property>
436
- </widget>
437
- </item>
438
- <item row="3" column="1">
439
- <widget class="QLineEdit" name="maxOFF_comboBox">
440
- <property name="sizePolicy">
441
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
442
- <horstretch>0</horstretch>
443
- <verstretch>0</verstretch>
444
- </sizepolicy>
445
- </property>
446
- <property name="placeholderText">
447
- <string>Range: 0 - 0.5</string>
448
- </property>
449
- </widget>
450
- </item>
451
- <item row="4" column="0">
452
- <widget class="QLabel" name="label_9">
453
- <property name="sizePolicy">
454
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
455
- <horstretch>0</horstretch>
456
- <verstretch>0</verstretch>
457
- </sizepolicy>
458
- </property>
459
- <property name="text">
460
- <string>Off-targeting progress:</string>
461
- </property>
462
- </widget>
463
- </item>
464
- <item row="3" column="0">
465
- <widget class="QLabel" name="label_8">
466
- <property name="sizePolicy">
467
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
468
- <horstretch>0</horstretch>
469
- <verstretch>0</verstretch>
470
- </sizepolicy>
471
- </property>
472
- <property name="toolTip">
473
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The maximum acceptable off-target score for guides in library. Range: 0-0.5, &lt;span style=&quot; font-weight:600;&quot;&gt;lower is better&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
474
- </property>
475
- <property name="text">
476
- <string>Maximum off-target score:</string>
477
- </property>
478
- </widget>
479
- </item>
480
- <item row="5" column="0" colspan="2">
481
- <spacer name="verticalSpacer_6">
482
- <property name="orientation">
483
- <enum>Qt::Vertical</enum>
484
- </property>
485
- <property name="sizeType">
486
- <enum>QSizePolicy::Fixed</enum>
487
- </property>
488
- <property name="sizeHint" stdset="0">
489
- <size>
490
- <width>10</width>
491
- <height>10</height>
492
- </size>
493
- </property>
494
- </spacer>
495
- </item>
496
- </layout>
497
- </widget>
498
- </item>
499
- <item row="2" column="0">
500
- <widget class="QGroupBox" name="Step1">
501
- <property name="sizePolicy">
502
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
503
- <horstretch>0</horstretch>
504
- <verstretch>0</verstretch>
505
- </sizepolicy>
506
- </property>
507
- <property name="title">
508
- <string>Step 1: Library Size and Location</string>
509
- </property>
510
- <layout class="QGridLayout" name="gridLayout_10">
511
- <item row="1" column="1" colspan="3">
512
- <widget class="QComboBox" name="numGenescomboBox">
513
- <property name="sizePolicy">
514
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
515
- <horstretch>0</horstretch>
516
- <verstretch>0</verstretch>
517
- </sizepolicy>
518
- </property>
519
- </widget>
520
- </item>
521
- <item row="2" column="0">
522
- <widget class="QLabel" name="label_3">
523
- <property name="sizePolicy">
524
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
525
- <horstretch>0</horstretch>
526
- <verstretch>0</verstretch>
527
- </sizepolicy>
528
- </property>
529
- <property name="toolTip">
530
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Percentage of gene to pull guides from. Default percentage is 100, meaning guides will be pulled from the entire gene, starting from the beginning.&lt;span style=&quot; font-weight:600;&quot;&gt; For example&lt;/span&gt;, Start = 50, End = 100 would pull guides from the second half of the gene, starting at 50.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
531
- </property>
532
- <property name="text">
533
- <string>Targeting range:</string>
534
- </property>
535
- </widget>
536
- </item>
537
- <item row="1" column="0">
538
- <widget class="QLabel" name="label_2">
539
- <property name="sizePolicy">
540
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
541
- <horstretch>0</horstretch>
542
- <verstretch>0</verstretch>
543
- </sizepolicy>
544
- </property>
545
- <property name="toolTip">
546
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;This is the number of guide RNAs that will be generated for each of the genes selected in Find Targets.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
547
- </property>
548
- <property name="text">
549
- <string>Number of guides per gene:</string>
550
- </property>
551
- </widget>
552
- </item>
553
- <item row="3" column="0" colspan="4">
554
- <widget class="QLabel" name="label_4">
555
- <property name="sizePolicy">
556
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
557
- <horstretch>0</horstretch>
558
- <verstretch>0</verstretch>
559
- </sizepolicy>
560
- </property>
561
- <property name="text">
562
- <string>(Start = 0, End = 100), pulls from the beginning</string>
563
- </property>
564
- </widget>
565
- </item>
566
- <item row="2" column="1">
567
- <widget class="QLineEdit" name="start_target_range">
568
- <property name="sizePolicy">
569
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
570
- <horstretch>0</horstretch>
571
- <verstretch>0</verstretch>
572
- </sizepolicy>
573
- </property>
574
- <property name="text">
575
- <string>0</string>
576
- </property>
577
- </widget>
578
- </item>
579
- <item row="2" column="2">
580
- <widget class="QLabel" name="label_5">
581
- <property name="sizePolicy">
582
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
583
- <horstretch>0</horstretch>
584
- <verstretch>0</verstretch>
585
- </sizepolicy>
586
- </property>
587
- <property name="text">
588
- <string>to</string>
589
- </property>
590
- <property name="alignment">
591
- <set>Qt::AlignCenter</set>
592
- </property>
593
- </widget>
594
- </item>
595
- <item row="2" column="3">
596
- <widget class="QLineEdit" name="end_target_range">
597
- <property name="sizePolicy">
598
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
599
- <horstretch>0</horstretch>
600
- <verstretch>0</verstretch>
601
- </sizepolicy>
602
- </property>
603
- <property name="text">
604
- <string>100</string>
605
- </property>
606
- </widget>
607
- </item>
608
- <item row="0" column="0" colspan="4">
609
- <spacer name="verticalSpacer_3">
610
- <property name="orientation">
611
- <enum>Qt::Vertical</enum>
612
- </property>
613
- <property name="sizeType">
614
- <enum>QSizePolicy::Fixed</enum>
615
- </property>
616
- <property name="sizeHint" stdset="0">
617
- <size>
618
- <width>10</width>
619
- <height>10</height>
620
- </size>
621
- </property>
622
- </spacer>
623
- </item>
624
- <item row="4" column="0" colspan="4">
625
- <spacer name="verticalSpacer_4">
626
- <property name="orientation">
627
- <enum>Qt::Vertical</enum>
628
- </property>
629
- <property name="sizeType">
630
- <enum>QSizePolicy::Fixed</enum>
631
- </property>
632
- <property name="sizeHint" stdset="0">
633
- <size>
634
- <width>10</width>
635
- <height>10</height>
636
- </size>
637
- </property>
638
- </spacer>
639
- </item>
640
- </layout>
641
- </widget>
642
- </item>
643
- </layout>
644
- </item>
645
- <item row="2" column="1">
646
- <spacer name="verticalSpacer">
647
- <property name="orientation">
648
- <enum>Qt::Vertical</enum>
649
- </property>
650
- <property name="sizeType">
651
- <enum>QSizePolicy::Fixed</enum>
652
- </property>
653
- <property name="sizeHint" stdset="0">
654
- <size>
655
- <width>20</width>
656
- <height>20</height>
657
- </size>
658
- </property>
659
- </spacer>
660
- </item>
661
- <item row="1" column="0">
662
- <spacer name="horizontalSpacer">
663
- <property name="orientation">
664
- <enum>Qt::Horizontal</enum>
665
- </property>
666
- <property name="sizeType">
667
- <enum>QSizePolicy::Fixed</enum>
668
- </property>
669
- <property name="sizeHint" stdset="0">
670
- <size>
671
- <width>20</width>
672
- <height>20</height>
673
- </size>
674
- </property>
675
- </spacer>
676
- </item>
677
- <item row="0" column="1">
678
- <spacer name="verticalSpacer_2">
679
- <property name="orientation">
680
- <enum>Qt::Vertical</enum>
681
- </property>
682
- <property name="sizeType">
683
- <enum>QSizePolicy::Fixed</enum>
684
- </property>
685
- <property name="sizeHint" stdset="0">
686
- <size>
687
- <width>20</width>
688
- <height>20</height>
689
- </size>
690
- </property>
691
- </spacer>
692
- </item>
693
- <item row="1" column="2">
694
- <spacer name="horizontalSpacer_2">
695
- <property name="orientation">
696
- <enum>Qt::Horizontal</enum>
697
- </property>
698
- <property name="sizeType">
699
- <enum>QSizePolicy::Fixed</enum>
700
- </property>
701
- <property name="sizeHint" stdset="0">
702
- <size>
703
- <width>20</width>
704
- <height>20</height>
705
- </size>
706
- </property>
707
- </spacer>
708
- </item>
709
- </layout>
710
- </widget>
711
- <widget class="QStatusBar" name="statusbar"/>
712
- </widget>
713
- <tabstops>
714
- <tabstop>numGenescomboBox</tabstop>
715
- <tabstop>start_target_range</tabstop>
716
- <tabstop>end_target_range</tabstop>
717
- <tabstop>find_off_Checkbox</tabstop>
718
- <tabstop>minON_comboBox</tabstop>
719
- <tabstop>maxOFF_comboBox</tabstop>
720
- <tabstop>space_line_edit</tabstop>
721
- <tabstop>fiveprimeseq</tabstop>
722
- <tabstop>modifyParamscheckBox</tabstop>
723
- <tabstop>filename_input</tabstop>
724
- <tabstop>output_path</tabstop>
725
- <tabstop>BrowseButton</tabstop>
726
- <tabstop>cancel_button</tabstop>
727
- <tabstop>submit_button</tabstop>
728
- </tabstops>
729
- <resources/>
730
- <connections/>
731
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/loading.ui DELETED
@@ -1,60 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>Form</class>
4
- <widget class="QWidget" name="Form">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>358</width>
10
- <height>224</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <family>Arial</family>
16
- <pointsize>1</pointsize>
17
- <weight>50</weight>
18
- <italic>false</italic>
19
- <bold>false</bold>
20
- </font>
21
- </property>
22
- <property name="windowTitle">
23
- <string>Loading file...</string>
24
- </property>
25
- <property name="styleSheet">
26
- <string notr="true"/>
27
- </property>
28
- <layout class="QGridLayout" name="gridLayout">
29
- <property name="sizeConstraint">
30
- <enum>QLayout::SetFixedSize</enum>
31
- </property>
32
- <item row="0" column="0">
33
- <widget class="QLabel" name="label">
34
- <property name="minimumSize">
35
- <size>
36
- <width>300</width>
37
- <height>100</height>
38
- </size>
39
- </property>
40
- <property name="font">
41
- <font>
42
- <family>Arial</family>
43
- <weight>50</weight>
44
- <italic>false</italic>
45
- <bold>false</bold>
46
- </font>
47
- </property>
48
- <property name="text">
49
- <string>Loading file, please wait.</string>
50
- </property>
51
- <property name="alignment">
52
- <set>Qt::AlignCenter</set>
53
- </property>
54
- </widget>
55
- </item>
56
- </layout>
57
- </widget>
58
- <resources/>
59
- <connections/>
60
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/loading_data_form.ui DELETED
@@ -1,129 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>450</width>
10
- <height>125</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="2" column="0" colspan="4">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="3">
40
- <spacer name="horizontalSpacer">
41
- <property name="orientation">
42
- <enum>Qt::Horizontal</enum>
43
- </property>
44
- <property name="sizeType">
45
- <enum>QSizePolicy::Fixed</enum>
46
- </property>
47
- <property name="sizeHint" stdset="0">
48
- <size>
49
- <width>20</width>
50
- <height>20</height>
51
- </size>
52
- </property>
53
- </spacer>
54
- </item>
55
- <item row="1" column="2">
56
- <layout class="QGridLayout" name="gridLayout">
57
- <item row="0" column="0">
58
- <layout class="QVBoxLayout" name="verticalLayout">
59
- <item>
60
- <widget class="QLabel" name="info_label">
61
- <property name="sizePolicy">
62
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
63
- <horstretch>0</horstretch>
64
- <verstretch>0</verstretch>
65
- </sizepolicy>
66
- </property>
67
- <property name="text">
68
- <string>Loading Data</string>
69
- </property>
70
- <property name="alignment">
71
- <set>Qt::AlignCenter</set>
72
- </property>
73
- </widget>
74
- </item>
75
- <item>
76
- <widget class="QProgressBar" name="loading_bar">
77
- <property name="sizePolicy">
78
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
79
- <horstretch>0</horstretch>
80
- <verstretch>0</verstretch>
81
- </sizepolicy>
82
- </property>
83
- <property name="value">
84
- <number>24</number>
85
- </property>
86
- </widget>
87
- </item>
88
- </layout>
89
- </item>
90
- </layout>
91
- </item>
92
- <item row="1" column="1">
93
- <spacer name="horizontalSpacer_2">
94
- <property name="orientation">
95
- <enum>Qt::Horizontal</enum>
96
- </property>
97
- <property name="sizeType">
98
- <enum>QSizePolicy::Fixed</enum>
99
- </property>
100
- <property name="sizeHint" stdset="0">
101
- <size>
102
- <width>20</width>
103
- <height>20</height>
104
- </size>
105
- </property>
106
- </spacer>
107
- </item>
108
- <item row="0" column="1" colspan="3">
109
- <spacer name="verticalSpacer_2">
110
- <property name="orientation">
111
- <enum>Qt::Vertical</enum>
112
- </property>
113
- <property name="sizeType">
114
- <enum>QSizePolicy::Fixed</enum>
115
- </property>
116
- <property name="sizeHint" stdset="0">
117
- <size>
118
- <width>20</width>
119
- <height>20</height>
120
- </size>
121
- </property>
122
- </spacer>
123
- </item>
124
- </layout>
125
- </widget>
126
- </widget>
127
- <resources/>
128
- <connections/>
129
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/mt.ui DELETED
@@ -1,553 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>1023</width>
10
- <height>765</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="1" column="1">
24
- <layout class="QGridLayout" name="gridLayout">
25
- <item row="2" column="0" rowspan="2">
26
- <widget class="QGroupBox" name="groupBox">
27
- <property name="sizePolicy">
28
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
29
- <horstretch>0</horstretch>
30
- <verstretch>0</verstretch>
31
- </sizepolicy>
32
- </property>
33
- <property name="title">
34
- <string>Select Organism and Endonuclease:</string>
35
- </property>
36
- <layout class="QGridLayout" name="gridLayout_8">
37
- <item row="2" column="0">
38
- <widget class="QComboBox" name="organism_drop">
39
- <property name="sizePolicy">
40
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
41
- <horstretch>0</horstretch>
42
- <verstretch>0</verstretch>
43
- </sizepolicy>
44
- </property>
45
- <property name="minimumSize">
46
- <size>
47
- <width>0</width>
48
- <height>0</height>
49
- </size>
50
- </property>
51
- </widget>
52
- </item>
53
- <item row="3" column="0" colspan="2">
54
- <layout class="QHBoxLayout" name="horizontalLayout">
55
- <item>
56
- <widget class="QPushButton" name="Analyze_Button">
57
- <property name="sizePolicy">
58
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
59
- <horstretch>0</horstretch>
60
- <verstretch>0</verstretch>
61
- </sizepolicy>
62
- </property>
63
- <property name="minimumSize">
64
- <size>
65
- <width>0</width>
66
- <height>0</height>
67
- </size>
68
- </property>
69
- <property name="text">
70
- <string>Analyze</string>
71
- </property>
72
- </widget>
73
- </item>
74
- <item>
75
- <widget class="QToolButton" name="sql_query_settings">
76
- <property name="minimumSize">
77
- <size>
78
- <width>0</width>
79
- <height>0</height>
80
- </size>
81
- </property>
82
- <property name="text">
83
- <string>...</string>
84
- </property>
85
- </widget>
86
- </item>
87
- </layout>
88
- </item>
89
- <item row="1" column="1">
90
- <widget class="QLabel" name="label_2">
91
- <property name="sizePolicy">
92
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
93
- <horstretch>0</horstretch>
94
- <verstretch>0</verstretch>
95
- </sizepolicy>
96
- </property>
97
- <property name="text">
98
- <string>Endonuclease</string>
99
- </property>
100
- </widget>
101
- </item>
102
- <item row="5" column="0" colspan="2">
103
- <widget class="QTableWidget" name="table">
104
- <property name="minimumSize">
105
- <size>
106
- <width>400</width>
107
- <height>0</height>
108
- </size>
109
- </property>
110
- </widget>
111
- </item>
112
- <item row="1" column="0">
113
- <widget class="QLabel" name="label">
114
- <property name="sizePolicy">
115
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
116
- <horstretch>0</horstretch>
117
- <verstretch>0</verstretch>
118
- </sizepolicy>
119
- </property>
120
- <property name="text">
121
- <string>Organism</string>
122
- </property>
123
- </widget>
124
- </item>
125
- <item row="2" column="1">
126
- <widget class="QComboBox" name="endo_drop">
127
- <property name="sizePolicy">
128
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
129
- <horstretch>0</horstretch>
130
- <verstretch>0</verstretch>
131
- </sizepolicy>
132
- </property>
133
- <property name="minimumSize">
134
- <size>
135
- <width>0</width>
136
- <height>0</height>
137
- </size>
138
- </property>
139
- </widget>
140
- </item>
141
- <item row="0" column="0" colspan="2">
142
- <spacer name="verticalSpacer_3">
143
- <property name="orientation">
144
- <enum>Qt::Vertical</enum>
145
- </property>
146
- <property name="sizeType">
147
- <enum>QSizePolicy::Fixed</enum>
148
- </property>
149
- <property name="sizeHint" stdset="0">
150
- <size>
151
- <width>10</width>
152
- <height>10</height>
153
- </size>
154
- </property>
155
- </spacer>
156
- </item>
157
- <item row="6" column="0" colspan="2">
158
- <spacer name="verticalSpacer_4">
159
- <property name="orientation">
160
- <enum>Qt::Vertical</enum>
161
- </property>
162
- <property name="sizeType">
163
- <enum>QSizePolicy::Fixed</enum>
164
- </property>
165
- <property name="sizeHint" stdset="0">
166
- <size>
167
- <width>10</width>
168
- <height>10</height>
169
- </size>
170
- </property>
171
- </spacer>
172
- </item>
173
- <item row="4" column="0">
174
- <widget class="QCheckBox" name="selectAll">
175
- <property name="text">
176
- <string>Select All</string>
177
- </property>
178
- </widget>
179
- </item>
180
- </layout>
181
- </widget>
182
- </item>
183
- <item row="2" column="1">
184
- <widget class="QGroupBox" name="groupBox_2">
185
- <property name="sizePolicy">
186
- <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
187
- <horstretch>0</horstretch>
188
- <verstretch>0</verstretch>
189
- </sizepolicy>
190
- </property>
191
- <property name="minimumSize">
192
- <size>
193
- <width>0</width>
194
- <height>0</height>
195
- </size>
196
- </property>
197
- <property name="title">
198
- <string>Seed Analysis</string>
199
- </property>
200
- <layout class="QGridLayout" name="gridLayout_6">
201
- <item row="3" column="0">
202
- <spacer name="verticalSpacer_8">
203
- <property name="orientation">
204
- <enum>Qt::Vertical</enum>
205
- </property>
206
- <property name="sizeType">
207
- <enum>QSizePolicy::Fixed</enum>
208
- </property>
209
- <property name="sizeHint" stdset="0">
210
- <size>
211
- <width>10</width>
212
- <height>10</height>
213
- </size>
214
- </property>
215
- </spacer>
216
- </item>
217
- <item row="0" column="0">
218
- <spacer name="verticalSpacer_7">
219
- <property name="orientation">
220
- <enum>Qt::Vertical</enum>
221
- </property>
222
- <property name="sizeType">
223
- <enum>QSizePolicy::Fixed</enum>
224
- </property>
225
- <property name="sizeHint" stdset="0">
226
- <size>
227
- <width>10</width>
228
- <height>10</height>
229
- </size>
230
- </property>
231
- </spacer>
232
- </item>
233
- <item row="1" column="0">
234
- <widget class="QTabWidget" name="tabWidget">
235
- <property name="sizePolicy">
236
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
237
- <horstretch>0</horstretch>
238
- <verstretch>0</verstretch>
239
- </sizepolicy>
240
- </property>
241
- <property name="minimumSize">
242
- <size>
243
- <width>0</width>
244
- <height>0</height>
245
- </size>
246
- </property>
247
- <property name="currentIndex">
248
- <number>0</number>
249
- </property>
250
- <widget class="QWidget" name="tab_3">
251
- <attribute name="title">
252
- <string>Scaffold/Chromosome Viewer:</string>
253
- </attribute>
254
- <layout class="QGridLayout" name="gridLayout_4">
255
- <item row="0" column="0">
256
- <widget class="QGraphicsView" name="graphicsView_2">
257
- <property name="sizePolicy">
258
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
259
- <horstretch>0</horstretch>
260
- <verstretch>0</verstretch>
261
- </sizepolicy>
262
- </property>
263
- <property name="maximumSize">
264
- <size>
265
- <width>16777215</width>
266
- <height>40</height>
267
- </size>
268
- </property>
269
- </widget>
270
- </item>
271
- <item row="1" column="0">
272
- <widget class="QScrollArea" name="scrollArea">
273
- <property name="sizePolicy">
274
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
275
- <horstretch>0</horstretch>
276
- <verstretch>0</verstretch>
277
- </sizepolicy>
278
- </property>
279
- <property name="widgetResizable">
280
- <bool>true</bool>
281
- </property>
282
- <widget class="QWidget" name="scrollAreaWidgetContents">
283
- <property name="geometry">
284
- <rect>
285
- <x>0</x>
286
- <y>0</y>
287
- <width>424</width>
288
- <height>121</height>
289
- </rect>
290
- </property>
291
- </widget>
292
- </widget>
293
- </item>
294
- </layout>
295
- </widget>
296
- <widget class="QWidget" name="tab_4">
297
- <attribute name="title">
298
- <string>Seed Distribution</string>
299
- </attribute>
300
- <layout class="QGridLayout" name="gridLayout_9">
301
- <item row="0" column="0">
302
- <widget class="QWidget" name="repeats_vs_chromo" native="true"/>
303
- </item>
304
- </layout>
305
- </widget>
306
- </widget>
307
- </item>
308
- </layout>
309
- </widget>
310
- </item>
311
- <item row="3" column="1">
312
- <widget class="QGroupBox" name="groupBox_3">
313
- <property name="sizePolicy">
314
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
315
- <horstretch>0</horstretch>
316
- <verstretch>0</verstretch>
317
- </sizepolicy>
318
- </property>
319
- <property name="minimumSize">
320
- <size>
321
- <width>0</width>
322
- <height>0</height>
323
- </size>
324
- </property>
325
- <property name="maximumSize">
326
- <size>
327
- <width>16777215</width>
328
- <height>16777215</height>
329
- </size>
330
- </property>
331
- <property name="title">
332
- <string>Global Analysis</string>
333
- </property>
334
- <layout class="QGridLayout" name="gridLayout_7">
335
- <item row="3" column="0">
336
- <spacer name="verticalSpacer_6">
337
- <property name="orientation">
338
- <enum>Qt::Vertical</enum>
339
- </property>
340
- <property name="sizeType">
341
- <enum>QSizePolicy::Fixed</enum>
342
- </property>
343
- <property name="sizeHint" stdset="0">
344
- <size>
345
- <width>10</width>
346
- <height>10</height>
347
- </size>
348
- </property>
349
- </spacer>
350
- </item>
351
- <item row="1" column="0">
352
- <widget class="QPushButton" name="statistics_overview">
353
- <property name="sizePolicy">
354
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
355
- <horstretch>0</horstretch>
356
- <verstretch>0</verstretch>
357
- </sizepolicy>
358
- </property>
359
- <property name="minimumSize">
360
- <size>
361
- <width>0</width>
362
- <height>0</height>
363
- </size>
364
- </property>
365
- <property name="text">
366
- <string>Statistics Overview</string>
367
- </property>
368
- </widget>
369
- </item>
370
- <item row="2" column="0">
371
- <widget class="QTabWidget" name="tabWidget_2">
372
- <property name="sizePolicy">
373
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
374
- <horstretch>0</horstretch>
375
- <verstretch>0</verstretch>
376
- </sizepolicy>
377
- </property>
378
- <property name="currentIndex">
379
- <number>1</number>
380
- </property>
381
- <widget class="QWidget" name="tab">
382
- <attribute name="title">
383
- <string>Repeats per ID Number</string>
384
- </attribute>
385
- <layout class="QGridLayout" name="gridLayout_11">
386
- <item row="0" column="0">
387
- <widget class="QWidget" name="repeats_vs_seeds_line" native="true"/>
388
- </item>
389
- </layout>
390
- </widget>
391
- <widget class="QWidget" name="tab_2">
392
- <attribute name="title">
393
- <string>Seeds per Number Repeats</string>
394
- </attribute>
395
- <layout class="QGridLayout" name="gridLayout_10">
396
- <item row="0" column="0">
397
- <widget class="QWidget" name="seeds_vs_repeats_bar" native="true">
398
- <property name="sizePolicy">
399
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
400
- <horstretch>0</horstretch>
401
- <verstretch>0</verstretch>
402
- </sizepolicy>
403
- </property>
404
- </widget>
405
- </item>
406
- </layout>
407
- </widget>
408
- </widget>
409
- </item>
410
- <item row="0" column="0">
411
- <spacer name="verticalSpacer_5">
412
- <property name="orientation">
413
- <enum>Qt::Vertical</enum>
414
- </property>
415
- <property name="sizeType">
416
- <enum>QSizePolicy::Fixed</enum>
417
- </property>
418
- <property name="sizeHint" stdset="0">
419
- <size>
420
- <width>10</width>
421
- <height>10</height>
422
- </size>
423
- </property>
424
- </spacer>
425
- </item>
426
- </layout>
427
- </widget>
428
- </item>
429
- <item row="0" column="0">
430
- <widget class="QLabel" name="title">
431
- <property name="text">
432
- <string>Multitargeting</string>
433
- </property>
434
- </widget>
435
- </item>
436
- <item row="1" column="0" colspan="2">
437
- <widget class="Line" name="line">
438
- <property name="orientation">
439
- <enum>Qt::Horizontal</enum>
440
- </property>
441
- </widget>
442
- </item>
443
- <item row="4" column="0" alignment="Qt::AlignLeft">
444
- <widget class="QPushButton" name="back_button">
445
- <property name="sizePolicy">
446
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
447
- <horstretch>0</horstretch>
448
- <verstretch>0</verstretch>
449
- </sizepolicy>
450
- </property>
451
- <property name="minimumSize">
452
- <size>
453
- <width>125</width>
454
- <height>0</height>
455
- </size>
456
- </property>
457
- <property name="text">
458
- <string>Back</string>
459
- </property>
460
- </widget>
461
- </item>
462
- <item row="4" column="1" alignment="Qt::AlignRight">
463
- <widget class="QPushButton" name="export_button">
464
- <property name="sizePolicy">
465
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
466
- <horstretch>0</horstretch>
467
- <verstretch>0</verstretch>
468
- </sizepolicy>
469
- </property>
470
- <property name="minimumSize">
471
- <size>
472
- <width>200</width>
473
- <height>0</height>
474
- </size>
475
- </property>
476
- <property name="text">
477
- <string>Export Selected gRNAs</string>
478
- </property>
479
- </widget>
480
- </item>
481
- </layout>
482
- </item>
483
- <item row="1" column="0">
484
- <spacer name="horizontalSpacer">
485
- <property name="orientation">
486
- <enum>Qt::Horizontal</enum>
487
- </property>
488
- <property name="sizeType">
489
- <enum>QSizePolicy::Fixed</enum>
490
- </property>
491
- <property name="sizeHint" stdset="0">
492
- <size>
493
- <width>20</width>
494
- <height>20</height>
495
- </size>
496
- </property>
497
- </spacer>
498
- </item>
499
- <item row="2" column="1">
500
- <spacer name="verticalSpacer">
501
- <property name="orientation">
502
- <enum>Qt::Vertical</enum>
503
- </property>
504
- <property name="sizeType">
505
- <enum>QSizePolicy::Fixed</enum>
506
- </property>
507
- <property name="sizeHint" stdset="0">
508
- <size>
509
- <width>20</width>
510
- <height>20</height>
511
- </size>
512
- </property>
513
- </spacer>
514
- </item>
515
- <item row="1" column="2">
516
- <spacer name="horizontalSpacer_2">
517
- <property name="orientation">
518
- <enum>Qt::Horizontal</enum>
519
- </property>
520
- <property name="sizeType">
521
- <enum>QSizePolicy::Fixed</enum>
522
- </property>
523
- <property name="sizeHint" stdset="0">
524
- <size>
525
- <width>20</width>
526
- <height>20</height>
527
- </size>
528
- </property>
529
- </spacer>
530
- </item>
531
- <item row="0" column="1">
532
- <spacer name="verticalSpacer_2">
533
- <property name="orientation">
534
- <enum>Qt::Vertical</enum>
535
- </property>
536
- <property name="sizeType">
537
- <enum>QSizePolicy::Fixed</enum>
538
- </property>
539
- <property name="sizeHint" stdset="0">
540
- <size>
541
- <width>20</width>
542
- <height>20</height>
543
- </size>
544
- </property>
545
- </spacer>
546
- </item>
547
- </layout>
548
- </widget>
549
- <widget class="QStatusBar" name="statusbar"/>
550
- </widget>
551
- <resources/>
552
- <connections/>
553
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/multitargeting_sql_settings.ui DELETED
@@ -1,149 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>375</width>
10
- <height>140</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="1" column="1">
24
- <layout class="QGridLayout" name="gridLayout">
25
- <item row="2" column="0">
26
- <widget class="QLabel" name="label">
27
- <property name="sizePolicy">
28
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
29
- <horstretch>0</horstretch>
30
- <verstretch>0</verstretch>
31
- </sizepolicy>
32
- </property>
33
- <property name="toolTip">
34
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Max table row count represents the max number of repeated seeds to be analyzed and loaded into the table in multitargeting. The &lt;span style=&quot; font-style:italic;&quot;&gt;global analysis&lt;/span&gt; section is not affected by this value. After changing the value, reload the anlysis but clicking the &lt;span style=&quot; font-weight:600;&quot;&gt;Analyze&lt;/span&gt; button.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
35
- </property>
36
- <property name="text">
37
- <string>Max Table Row Count:</string>
38
- </property>
39
- </widget>
40
- </item>
41
- <item row="2" column="1">
42
- <widget class="QLineEdit" name="row_count">
43
- <property name="sizePolicy">
44
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
45
- <horstretch>0</horstretch>
46
- <verstretch>0</verstretch>
47
- </sizepolicy>
48
- </property>
49
- <property name="toolTip">
50
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Default value is 1000. Change to -1 for no limit.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
51
- </property>
52
- <property name="text">
53
- <string>1000</string>
54
- </property>
55
- </widget>
56
- </item>
57
- <item row="1" column="0" colspan="2">
58
- <widget class="Line" name="line">
59
- <property name="orientation">
60
- <enum>Qt::Horizontal</enum>
61
- </property>
62
- </widget>
63
- </item>
64
- <item row="0" column="0" colspan="2">
65
- <widget class="QLabel" name="title">
66
- <property name="sizePolicy">
67
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
68
- <horstretch>0</horstretch>
69
- <verstretch>0</verstretch>
70
- </sizepolicy>
71
- </property>
72
- <property name="text">
73
- <string>SQL Settings</string>
74
- </property>
75
- </widget>
76
- </item>
77
- </layout>
78
- </item>
79
- <item row="1" column="2">
80
- <spacer name="horizontalSpacer_2">
81
- <property name="orientation">
82
- <enum>Qt::Horizontal</enum>
83
- </property>
84
- <property name="sizeType">
85
- <enum>QSizePolicy::Fixed</enum>
86
- </property>
87
- <property name="sizeHint" stdset="0">
88
- <size>
89
- <width>20</width>
90
- <height>20</height>
91
- </size>
92
- </property>
93
- </spacer>
94
- </item>
95
- <item row="1" column="0">
96
- <spacer name="horizontalSpacer">
97
- <property name="orientation">
98
- <enum>Qt::Horizontal</enum>
99
- </property>
100
- <property name="sizeType">
101
- <enum>QSizePolicy::Fixed</enum>
102
- </property>
103
- <property name="sizeHint" stdset="0">
104
- <size>
105
- <width>20</width>
106
- <height>20</height>
107
- </size>
108
- </property>
109
- </spacer>
110
- </item>
111
- <item row="2" column="1">
112
- <spacer name="verticalSpacer">
113
- <property name="orientation">
114
- <enum>Qt::Vertical</enum>
115
- </property>
116
- <property name="sizeType">
117
- <enum>QSizePolicy::Fixed</enum>
118
- </property>
119
- <property name="sizeHint" stdset="0">
120
- <size>
121
- <width>20</width>
122
- <height>20</height>
123
- </size>
124
- </property>
125
- </spacer>
126
- </item>
127
- <item row="0" column="1">
128
- <spacer name="verticalSpacer_2">
129
- <property name="orientation">
130
- <enum>Qt::Vertical</enum>
131
- </property>
132
- <property name="sizeType">
133
- <enum>QSizePolicy::Fixed</enum>
134
- </property>
135
- <property name="sizeHint" stdset="0">
136
- <size>
137
- <width>20</width>
138
- <height>20</height>
139
- </size>
140
- </property>
141
- </spacer>
142
- </item>
143
- </layout>
144
- </widget>
145
- <widget class="QStatusBar" name="statusbar"/>
146
- </widget>
147
- <resources/>
148
- <connections/>
149
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/multitargeting_stats.ui DELETED
@@ -1,227 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>350</width>
10
- <height>250</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="2" column="1">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="2">
40
- <spacer name="horizontalSpacer_2">
41
- <property name="orientation">
42
- <enum>Qt::Horizontal</enum>
43
- </property>
44
- <property name="sizeType">
45
- <enum>QSizePolicy::Fixed</enum>
46
- </property>
47
- <property name="sizeHint" stdset="0">
48
- <size>
49
- <width>20</width>
50
- <height>20</height>
51
- </size>
52
- </property>
53
- </spacer>
54
- </item>
55
- <item row="1" column="0">
56
- <spacer name="horizontalSpacer">
57
- <property name="orientation">
58
- <enum>Qt::Horizontal</enum>
59
- </property>
60
- <property name="sizeType">
61
- <enum>QSizePolicy::Fixed</enum>
62
- </property>
63
- <property name="sizeHint" stdset="0">
64
- <size>
65
- <width>20</width>
66
- <height>20</height>
67
- </size>
68
- </property>
69
- </spacer>
70
- </item>
71
- <item row="0" column="1">
72
- <spacer name="verticalSpacer_2">
73
- <property name="orientation">
74
- <enum>Qt::Vertical</enum>
75
- </property>
76
- <property name="sizeType">
77
- <enum>QSizePolicy::Fixed</enum>
78
- </property>
79
- <property name="sizeHint" stdset="0">
80
- <size>
81
- <width>20</width>
82
- <height>20</height>
83
- </size>
84
- </property>
85
- </spacer>
86
- </item>
87
- <item row="1" column="1">
88
- <layout class="QGridLayout" name="gridLayout">
89
- <item row="2" column="0">
90
- <widget class="QLabel" name="label_2">
91
- <property name="sizePolicy">
92
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
93
- <horstretch>0</horstretch>
94
- <verstretch>0</verstretch>
95
- </sizepolicy>
96
- </property>
97
- <property name="text">
98
- <string>Total Number of Repeats:</string>
99
- </property>
100
- </widget>
101
- </item>
102
- <item row="4" column="0">
103
- <widget class="QLabel" name="label_4">
104
- <property name="sizePolicy">
105
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
106
- <horstretch>0</horstretch>
107
- <verstretch>0</verstretch>
108
- </sizepolicy>
109
- </property>
110
- <property name="text">
111
- <string>Median Number of Repeats:</string>
112
- </property>
113
- </widget>
114
- </item>
115
- <item row="5" column="0">
116
- <widget class="QLabel" name="label_5">
117
- <property name="sizePolicy">
118
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
119
- <horstretch>0</horstretch>
120
- <verstretch>0</verstretch>
121
- </sizepolicy>
122
- </property>
123
- <property name="text">
124
- <string>Mode Number of Repeats:</string>
125
- </property>
126
- </widget>
127
- </item>
128
- <item row="3" column="0">
129
- <widget class="QLabel" name="label_3">
130
- <property name="sizePolicy">
131
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
132
- <horstretch>0</horstretch>
133
- <verstretch>0</verstretch>
134
- </sizepolicy>
135
- </property>
136
- <property name="text">
137
- <string>Average Number of Repeats:</string>
138
- </property>
139
- </widget>
140
- </item>
141
- <item row="2" column="1">
142
- <widget class="QLabel" name="nbr_seq">
143
- <property name="sizePolicy">
144
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
145
- <horstretch>0</horstretch>
146
- <verstretch>0</verstretch>
147
- </sizepolicy>
148
- </property>
149
- <property name="text">
150
- <string/>
151
- </property>
152
- </widget>
153
- </item>
154
- <item row="3" column="1">
155
- <widget class="QLabel" name="avg_rep">
156
- <property name="sizePolicy">
157
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
158
- <horstretch>0</horstretch>
159
- <verstretch>0</verstretch>
160
- </sizepolicy>
161
- </property>
162
- <property name="text">
163
- <string/>
164
- </property>
165
- </widget>
166
- </item>
167
- <item row="4" column="1">
168
- <widget class="QLabel" name="med_rep">
169
- <property name="sizePolicy">
170
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
171
- <horstretch>0</horstretch>
172
- <verstretch>0</verstretch>
173
- </sizepolicy>
174
- </property>
175
- <property name="text">
176
- <string/>
177
- </property>
178
- </widget>
179
- </item>
180
- <item row="5" column="1">
181
- <widget class="QLabel" name="mode_rep">
182
- <property name="sizePolicy">
183
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
184
- <horstretch>0</horstretch>
185
- <verstretch>0</verstretch>
186
- </sizepolicy>
187
- </property>
188
- <property name="text">
189
- <string/>
190
- </property>
191
- </widget>
192
- </item>
193
- <item row="0" column="0" colspan="2">
194
- <widget class="QLabel" name="title">
195
- <property name="sizePolicy">
196
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
197
- <horstretch>0</horstretch>
198
- <verstretch>0</verstretch>
199
- </sizepolicy>
200
- </property>
201
- <property name="text">
202
- <string>Multitargeting Statistics</string>
203
- </property>
204
- </widget>
205
- </item>
206
- <item row="1" column="0" colspan="2">
207
- <widget class="Line" name="line">
208
- <property name="sizePolicy">
209
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
210
- <horstretch>0</horstretch>
211
- <verstretch>0</verstretch>
212
- </sizepolicy>
213
- </property>
214
- <property name="orientation">
215
- <enum>Qt::Horizontal</enum>
216
- </property>
217
- </widget>
218
- </item>
219
- </layout>
220
- </item>
221
- </layout>
222
- </widget>
223
- <widget class="QStatusBar" name="statusbar"/>
224
- </widget>
225
- <resources/>
226
- <connections/>
227
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/name_form.ui DELETED
@@ -1,46 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>ShowNames</class>
4
- <widget class="QWidget" name="ShowNames">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>582</width>
10
- <height>314</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <family>Arial</family>
16
- <pointsize>1</pointsize>
17
- <weight>50</weight>
18
- <italic>false</italic>
19
- <bold>false</bold>
20
- </font>
21
- </property>
22
- <property name="windowTitle">
23
- <string>Show Names</string>
24
- </property>
25
- <property name="styleSheet">
26
- <string notr="true"/>
27
- </property>
28
- <layout class="QGridLayout" name="gridLayout">
29
- <property name="sizeConstraint">
30
- <enum>QLayout::SetFixedSize</enum>
31
- </property>
32
- <item row="0" column="0">
33
- <widget class="QTableWidget" name="name_table">
34
- <property name="minimumSize">
35
- <size>
36
- <width>558</width>
37
- <height>290</height>
38
- </size>
39
- </property>
40
- </widget>
41
- </item>
42
- </layout>
43
- </widget>
44
- <resources/>
45
- <connections/>
46
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/ncbi.ui DELETED
@@ -1,494 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>865</width>
10
- <height>723</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="2" column="1">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="0">
40
- <spacer name="horizontalSpacer">
41
- <property name="orientation">
42
- <enum>Qt::Horizontal</enum>
43
- </property>
44
- <property name="sizeType">
45
- <enum>QSizePolicy::Fixed</enum>
46
- </property>
47
- <property name="sizeHint" stdset="0">
48
- <size>
49
- <width>20</width>
50
- <height>20</height>
51
- </size>
52
- </property>
53
- </spacer>
54
- </item>
55
- <item row="1" column="1">
56
- <layout class="QGridLayout" name="gridLayout">
57
- <item row="3" column="0" colspan="2">
58
- <widget class="QGroupBox" name="Step2">
59
- <property name="title">
60
- <string>Step 2: Search and Select Files</string>
61
- </property>
62
- <layout class="QGridLayout" name="gridLayout_6">
63
- <item row="1" column="0" alignment="Qt::AlignLeft">
64
- <widget class="QPushButton" name="search_button">
65
- <property name="minimumSize">
66
- <size>
67
- <width>125</width>
68
- <height>0</height>
69
- </size>
70
- </property>
71
- <property name="text">
72
- <string>Search</string>
73
- </property>
74
- </widget>
75
- </item>
76
- <item row="3" column="0" colspan="3">
77
- <spacer name="verticalSpacer_6">
78
- <property name="orientation">
79
- <enum>Qt::Vertical</enum>
80
- </property>
81
- <property name="sizeType">
82
- <enum>QSizePolicy::Fixed</enum>
83
- </property>
84
- <property name="sizeHint" stdset="0">
85
- <size>
86
- <width>10</width>
87
- <height>10</height>
88
- </size>
89
- </property>
90
- </spacer>
91
- </item>
92
- <item row="0" column="0" colspan="3">
93
- <spacer name="verticalSpacer_5">
94
- <property name="orientation">
95
- <enum>Qt::Vertical</enum>
96
- </property>
97
- <property name="sizeType">
98
- <enum>QSizePolicy::Fixed</enum>
99
- </property>
100
- <property name="sizeHint" stdset="0">
101
- <size>
102
- <width>10</width>
103
- <height>10</height>
104
- </size>
105
- </property>
106
- </spacer>
107
- </item>
108
- <item row="2" column="0" colspan="3">
109
- <widget class="QTableView" name="ncbi_table">
110
- <property name="layoutDirection">
111
- <enum>Qt::LeftToRight</enum>
112
- </property>
113
- </widget>
114
- </item>
115
- <item row="1" column="2" alignment="Qt::AlignRight">
116
- <widget class="QCheckBox" name="all_rows">
117
- <property name="text">
118
- <string>Select all rows</string>
119
- </property>
120
- </widget>
121
- </item>
122
- </layout>
123
- </widget>
124
- </item>
125
- <item row="0" column="1">
126
- <widget class="QLabel" name="label_2">
127
- <property name="text">
128
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#ff0000;&quot;&gt;* Required&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
129
- </property>
130
- <property name="alignment">
131
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
132
- </property>
133
- </widget>
134
- </item>
135
- <item row="1" column="0" colspan="2">
136
- <widget class="Line" name="line">
137
- <property name="orientation">
138
- <enum>Qt::Horizontal</enum>
139
- </property>
140
- </widget>
141
- </item>
142
- <item row="2" column="0">
143
- <widget class="QGroupBox" name="Step1">
144
- <property name="sizePolicy">
145
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
146
- <horstretch>0</horstretch>
147
- <verstretch>0</verstretch>
148
- </sizepolicy>
149
- </property>
150
- <property name="title">
151
- <string>Step 1: Input Search Options</string>
152
- </property>
153
- <layout class="QGridLayout" name="gridLayout_4">
154
- <item row="2" column="0">
155
- <widget class="QLabel" name="label_3">
156
- <property name="sizePolicy">
157
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
158
- <horstretch>0</horstretch>
159
- <verstretch>0</verstretch>
160
- </sizepolicy>
161
- </property>
162
- <property name="text">
163
- <string>Strain Designation</string>
164
- </property>
165
- </widget>
166
- </item>
167
- <item row="3" column="0">
168
- <widget class="QLabel" name="label_4">
169
- <property name="sizePolicy">
170
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
171
- <horstretch>0</horstretch>
172
- <verstretch>0</verstretch>
173
- </sizepolicy>
174
- </property>
175
- <property name="toolTip">
176
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Number of search results to return.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
177
- </property>
178
- <property name="text">
179
- <string>Return Max (Default = 100)</string>
180
- </property>
181
- </widget>
182
- </item>
183
- <item row="4" column="0">
184
- <widget class="QLabel" name="label_5">
185
- <property name="sizePolicy">
186
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
187
- <horstretch>0</horstretch>
188
- <verstretch>0</verstretch>
189
- </sizepolicy>
190
- </property>
191
- <property name="toolTip">
192
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Only display entries classified as &amp;quot;Complete Genomes&amp;quot; by NCBI.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
193
- </property>
194
- <property name="text">
195
- <string>Complete Genomes Only</string>
196
- </property>
197
- </widget>
198
- </item>
199
- <item row="1" column="0">
200
- <widget class="QLabel" name="label">
201
- <property name="sizePolicy">
202
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
203
- <horstretch>0</horstretch>
204
- <verstretch>0</verstretch>
205
- </sizepolicy>
206
- </property>
207
- <property name="text">
208
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#ff0000;&quot;&gt;* &lt;/span&gt;Organism&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
209
- </property>
210
- </widget>
211
- </item>
212
- <item row="1" column="1">
213
- <widget class="QLineEdit" name="organism_line_edit">
214
- <property name="placeholderText">
215
- <string>Ex. Escherchia coli</string>
216
- </property>
217
- </widget>
218
- </item>
219
- <item row="2" column="1">
220
- <widget class="QLineEdit" name="infra_name_line_edit">
221
- <property name="placeholderText">
222
- <string>Ex. K-12</string>
223
- </property>
224
- </widget>
225
- </item>
226
- <item row="3" column="1">
227
- <widget class="QLineEdit" name="ret_max_line_edit">
228
- <property name="text">
229
- <string>100</string>
230
- </property>
231
- </widget>
232
- </item>
233
- <item row="4" column="1">
234
- <widget class="QCheckBox" name="yes_box">
235
- <property name="text">
236
- <string/>
237
- </property>
238
- </widget>
239
- </item>
240
- <item row="5" column="0" colspan="2">
241
- <spacer name="verticalSpacer_3">
242
- <property name="orientation">
243
- <enum>Qt::Vertical</enum>
244
- </property>
245
- <property name="sizeType">
246
- <enum>QSizePolicy::Fixed</enum>
247
- </property>
248
- <property name="sizeHint" stdset="0">
249
- <size>
250
- <width>10</width>
251
- <height>10</height>
252
- </size>
253
- </property>
254
- </spacer>
255
- </item>
256
- <item row="0" column="0" colspan="2">
257
- <spacer name="verticalSpacer_4">
258
- <property name="orientation">
259
- <enum>Qt::Vertical</enum>
260
- </property>
261
- <property name="sizeType">
262
- <enum>QSizePolicy::Fixed</enum>
263
- </property>
264
- <property name="sizeHint" stdset="0">
265
- <size>
266
- <width>10</width>
267
- <height>10</height>
268
- </size>
269
- </property>
270
- </spacer>
271
- </item>
272
- </layout>
273
- </widget>
274
- </item>
275
- <item row="0" column="0">
276
- <widget class="QLabel" name="title">
277
- <property name="sizePolicy">
278
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
279
- <horstretch>0</horstretch>
280
- <verstretch>0</verstretch>
281
- </sizepolicy>
282
- </property>
283
- <property name="text">
284
- <string>NCBI Tool</string>
285
- </property>
286
- </widget>
287
- </item>
288
- <item row="2" column="1">
289
- <widget class="QGroupBox" name="Step3">
290
- <property name="sizePolicy">
291
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
292
- <horstretch>0</horstretch>
293
- <verstretch>0</verstretch>
294
- </sizepolicy>
295
- </property>
296
- <property name="title">
297
- <string>Step 3: Download Files</string>
298
- </property>
299
- <layout class="QGridLayout" name="gridLayout_5">
300
- <item row="7" column="0" colspan="3">
301
- <spacer name="verticalSpacer_8">
302
- <property name="orientation">
303
- <enum>Qt::Vertical</enum>
304
- </property>
305
- <property name="sizeType">
306
- <enum>QSizePolicy::Fixed</enum>
307
- </property>
308
- <property name="sizeHint" stdset="0">
309
- <size>
310
- <width>10</width>
311
- <height>10</height>
312
- </size>
313
- </property>
314
- </spacer>
315
- </item>
316
- <item row="2" column="2">
317
- <widget class="QCheckBox" name="fna_checkbox">
318
- <property name="text">
319
- <string>FASTA/FNA</string>
320
- </property>
321
- <property name="checked">
322
- <bool>true</bool>
323
- </property>
324
- </widget>
325
- </item>
326
- <item row="3" column="0">
327
- <widget class="QPushButton" name="download_button">
328
- <property name="minimumSize">
329
- <size>
330
- <width>125</width>
331
- <height>0</height>
332
- </size>
333
- </property>
334
- <property name="text">
335
- <string>Download Files</string>
336
- </property>
337
- </widget>
338
- </item>
339
- <item row="2" column="0">
340
- <widget class="QLabel" name="label_7">
341
- <property name="toolTip">
342
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;These are the file types that you are choosing to download. GBFF = annotation file, FASTA/FNA = genomic sequence file.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
343
- </property>
344
- <property name="text">
345
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#ff0000;&quot;&gt;*&lt;/span&gt; File Types:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
346
- </property>
347
- </widget>
348
- </item>
349
- <item row="1" column="2">
350
- <widget class="QRadioButton" name="refseq_checkbox">
351
- <property name="text">
352
- <string>RefSeq</string>
353
- </property>
354
- <property name="checked">
355
- <bool>true</bool>
356
- </property>
357
- </widget>
358
- </item>
359
- <item row="2" column="1">
360
- <widget class="QCheckBox" name="gbff_checkbox">
361
- <property name="text">
362
- <string>GBFF</string>
363
- </property>
364
- <property name="checked">
365
- <bool>true</bool>
366
- </property>
367
- </widget>
368
- </item>
369
- <item row="1" column="1">
370
- <widget class="QRadioButton" name="genbank_checkbox">
371
- <property name="text">
372
- <string>GenBank</string>
373
- </property>
374
- </widget>
375
- </item>
376
- <item row="0" column="0" colspan="3">
377
- <spacer name="verticalSpacer_7">
378
- <property name="orientation">
379
- <enum>Qt::Vertical</enum>
380
- </property>
381
- <property name="sizeType">
382
- <enum>QSizePolicy::Fixed</enum>
383
- </property>
384
- <property name="sizeHint" stdset="0">
385
- <size>
386
- <width>10</width>
387
- <height>10</height>
388
- </size>
389
- </property>
390
- </spacer>
391
- </item>
392
- <item row="1" column="0">
393
- <widget class="QLabel" name="label_6">
394
- <property name="toolTip">
395
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;These are the databases that files are downloaded from. Refseq is considered the gold standard for annotations and assemblies. It is HIGHLY recommended to use Refseq if available for the genome of interest.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
396
- </property>
397
- <property name="text">
398
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#ff0000;&quot;&gt;*&lt;/span&gt; Collections:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
399
- </property>
400
- </widget>
401
- </item>
402
- <item row="3" column="1" colspan="2">
403
- <widget class="QLabel" name="progressLabel">
404
- <property name="text">
405
- <string/>
406
- </property>
407
- </widget>
408
- </item>
409
- <item row="4" column="0" colspan="3">
410
- <widget class="QProgressBar" name="progressBar">
411
- <property name="value">
412
- <number>24</number>
413
- </property>
414
- </widget>
415
- </item>
416
- <item row="6" column="0" colspan="3">
417
- <layout class="QFormLayout" name="formLayout">
418
- <property name="fieldGrowthPolicy">
419
- <enum>QFormLayout::ExpandingFieldsGrow</enum>
420
- </property>
421
- </layout>
422
- </item>
423
- </layout>
424
- </widget>
425
- </item>
426
- <item row="4" column="0" alignment="Qt::AlignLeft">
427
- <widget class="QPushButton" name="back_button">
428
- <property name="minimumSize">
429
- <size>
430
- <width>125</width>
431
- <height>0</height>
432
- </size>
433
- </property>
434
- <property name="text">
435
- <string>Back</string>
436
- </property>
437
- </widget>
438
- </item>
439
- </layout>
440
- </item>
441
- <item row="1" column="2">
442
- <spacer name="horizontalSpacer_2">
443
- <property name="orientation">
444
- <enum>Qt::Horizontal</enum>
445
- </property>
446
- <property name="sizeType">
447
- <enum>QSizePolicy::Fixed</enum>
448
- </property>
449
- <property name="sizeHint" stdset="0">
450
- <size>
451
- <width>20</width>
452
- <height>20</height>
453
- </size>
454
- </property>
455
- </spacer>
456
- </item>
457
- <item row="0" column="1">
458
- <spacer name="verticalSpacer_2">
459
- <property name="orientation">
460
- <enum>Qt::Vertical</enum>
461
- </property>
462
- <property name="sizeType">
463
- <enum>QSizePolicy::Fixed</enum>
464
- </property>
465
- <property name="sizeHint" stdset="0">
466
- <size>
467
- <width>20</width>
468
- <height>20</height>
469
- </size>
470
- </property>
471
- </spacer>
472
- </item>
473
- </layout>
474
- </widget>
475
- <widget class="QStatusBar" name="statusbar"/>
476
- </widget>
477
- <tabstops>
478
- <tabstop>organism_line_edit</tabstop>
479
- <tabstop>infra_name_line_edit</tabstop>
480
- <tabstop>ret_max_line_edit</tabstop>
481
- <tabstop>yes_box</tabstop>
482
- <tabstop>search_button</tabstop>
483
- <tabstop>all_rows</tabstop>
484
- <tabstop>ncbi_table</tabstop>
485
- <tabstop>genbank_checkbox</tabstop>
486
- <tabstop>refseq_checkbox</tabstop>
487
- <tabstop>gbff_checkbox</tabstop>
488
- <tabstop>fna_checkbox</tabstop>
489
- <tabstop>download_button</tabstop>
490
- <tabstop>back_button</tabstop>
491
- </tabstops>
492
- <resources/>
493
- <connections/>
494
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/ncbi_nav_page.ui DELETED
@@ -1,172 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>575</width>
10
- <height>225</height>
11
- </rect>
12
- </property>
13
- <property name="windowTitle">
14
- <string>MainWindow</string>
15
- </property>
16
- <widget class="QWidget" name="centralwidget">
17
- <layout class="QGridLayout" name="gridLayout_2">
18
- <item row="1" column="2">
19
- <spacer name="horizontalSpacer_2">
20
- <property name="orientation">
21
- <enum>Qt::Horizontal</enum>
22
- </property>
23
- <property name="sizeType">
24
- <enum>QSizePolicy::Fixed</enum>
25
- </property>
26
- <property name="sizeHint" stdset="0">
27
- <size>
28
- <width>20</width>
29
- <height>20</height>
30
- </size>
31
- </property>
32
- </spacer>
33
- </item>
34
- <item row="2" column="1">
35
- <spacer name="verticalSpacer">
36
- <property name="orientation">
37
- <enum>Qt::Vertical</enum>
38
- </property>
39
- <property name="sizeType">
40
- <enum>QSizePolicy::Fixed</enum>
41
- </property>
42
- <property name="sizeHint" stdset="0">
43
- <size>
44
- <width>20</width>
45
- <height>20</height>
46
- </size>
47
- </property>
48
- </spacer>
49
- </item>
50
- <item row="1" column="1">
51
- <layout class="QGridLayout" name="gridLayout">
52
- <item row="0" column="0">
53
- <widget class="QGroupBox" name="groupBox">
54
- <property name="title">
55
- <string>NCBI</string>
56
- </property>
57
- <layout class="QGridLayout" name="gridLayout_3">
58
- <item row="0" column="0" colspan="2">
59
- <spacer name="verticalSpacer_3">
60
- <property name="orientation">
61
- <enum>Qt::Vertical</enum>
62
- </property>
63
- <property name="sizeType">
64
- <enum>QSizePolicy::Fixed</enum>
65
- </property>
66
- <property name="sizeHint" stdset="0">
67
- <size>
68
- <width>10</width>
69
- <height>10</height>
70
- </size>
71
- </property>
72
- </spacer>
73
- </item>
74
- <item row="2" column="1">
75
- <widget class="QPushButton" name="stay">
76
- <property name="sizePolicy">
77
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
78
- <horstretch>0</horstretch>
79
- <verstretch>0</verstretch>
80
- </sizepolicy>
81
- </property>
82
- <property name="toolTip">
83
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Keep the NCBI tool open to browse more files.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
84
- </property>
85
- <property name="text">
86
- <string>Download More Files</string>
87
- </property>
88
- </widget>
89
- </item>
90
- <item row="3" column="0" colspan="2">
91
- <spacer name="verticalSpacer_4">
92
- <property name="orientation">
93
- <enum>Qt::Vertical</enum>
94
- </property>
95
- <property name="sizeType">
96
- <enum>QSizePolicy::Fixed</enum>
97
- </property>
98
- <property name="sizeHint" stdset="0">
99
- <size>
100
- <width>10</width>
101
- <height>10</height>
102
- </size>
103
- </property>
104
- </spacer>
105
- </item>
106
- <item row="2" column="0">
107
- <widget class="QPushButton" name="close">
108
- <property name="sizePolicy">
109
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
110
- <horstretch>0</horstretch>
111
- <verstretch>0</verstretch>
112
- </sizepolicy>
113
- </property>
114
- <property name="toolTip">
115
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Close the NCBI tool to contiue working on previous tasks.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
116
- </property>
117
- <property name="text">
118
- <string>Close NCBI</string>
119
- </property>
120
- </widget>
121
- </item>
122
- <item row="1" column="0" colspan="2">
123
- <widget class="QLabel" name="label">
124
- <property name="text">
125
- <string/>
126
- </property>
127
- </widget>
128
- </item>
129
- </layout>
130
- </widget>
131
- </item>
132
- </layout>
133
- </item>
134
- <item row="1" column="0">
135
- <spacer name="horizontalSpacer">
136
- <property name="orientation">
137
- <enum>Qt::Horizontal</enum>
138
- </property>
139
- <property name="sizeType">
140
- <enum>QSizePolicy::Fixed</enum>
141
- </property>
142
- <property name="sizeHint" stdset="0">
143
- <size>
144
- <width>20</width>
145
- <height>20</height>
146
- </size>
147
- </property>
148
- </spacer>
149
- </item>
150
- <item row="0" column="1">
151
- <spacer name="verticalSpacer_2">
152
- <property name="orientation">
153
- <enum>Qt::Vertical</enum>
154
- </property>
155
- <property name="sizeType">
156
- <enum>QSizePolicy::Fixed</enum>
157
- </property>
158
- <property name="sizeHint" stdset="0">
159
- <size>
160
- <width>20</width>
161
- <height>20</height>
162
- </size>
163
- </property>
164
- </spacer>
165
- </item>
166
- </layout>
167
- </widget>
168
- <widget class="QStatusBar" name="statusbar"/>
169
- </widget>
170
- <resources/>
171
- <connections/>
172
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/ncbi_rename_window.ui DELETED
@@ -1,121 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>650</width>
10
- <height>400</height>
11
- </rect>
12
- </property>
13
- <property name="windowTitle">
14
- <string>MainWindow</string>
15
- </property>
16
- <widget class="QWidget" name="centralwidget">
17
- <layout class="QGridLayout" name="gridLayout_2">
18
- <item row="1" column="1">
19
- <layout class="QGridLayout" name="gridLayout">
20
- <item row="1" column="0" alignment="Qt::AlignLeft">
21
- <widget class="QPushButton" name="go_back">
22
- <property name="minimumSize">
23
- <size>
24
- <width>125</width>
25
- <height>0</height>
26
- </size>
27
- </property>
28
- <property name="text">
29
- <string>Go Back</string>
30
- </property>
31
- </widget>
32
- </item>
33
- <item row="1" column="1" alignment="Qt::AlignRight">
34
- <widget class="QPushButton" name="submit_button">
35
- <property name="minimumSize">
36
- <size>
37
- <width>125</width>
38
- <height>0</height>
39
- </size>
40
- </property>
41
- <property name="text">
42
- <string>Submit</string>
43
- </property>
44
- </widget>
45
- </item>
46
- <item row="0" column="0" colspan="2">
47
- <widget class="QTableWidget" name="rename_table"/>
48
- </item>
49
- </layout>
50
- </item>
51
- <item row="1" column="2">
52
- <spacer name="horizontalSpacer">
53
- <property name="orientation">
54
- <enum>Qt::Horizontal</enum>
55
- </property>
56
- <property name="sizeType">
57
- <enum>QSizePolicy::Fixed</enum>
58
- </property>
59
- <property name="sizeHint" stdset="0">
60
- <size>
61
- <width>20</width>
62
- <height>20</height>
63
- </size>
64
- </property>
65
- </spacer>
66
- </item>
67
- <item row="2" column="1">
68
- <spacer name="verticalSpacer">
69
- <property name="orientation">
70
- <enum>Qt::Vertical</enum>
71
- </property>
72
- <property name="sizeType">
73
- <enum>QSizePolicy::Fixed</enum>
74
- </property>
75
- <property name="sizeHint" stdset="0">
76
- <size>
77
- <width>20</width>
78
- <height>20</height>
79
- </size>
80
- </property>
81
- </spacer>
82
- </item>
83
- <item row="0" column="1">
84
- <spacer name="verticalSpacer_2">
85
- <property name="orientation">
86
- <enum>Qt::Vertical</enum>
87
- </property>
88
- <property name="sizeType">
89
- <enum>QSizePolicy::Fixed</enum>
90
- </property>
91
- <property name="sizeHint" stdset="0">
92
- <size>
93
- <width>20</width>
94
- <height>20</height>
95
- </size>
96
- </property>
97
- </spacer>
98
- </item>
99
- <item row="1" column="0">
100
- <spacer name="horizontalSpacer_2">
101
- <property name="orientation">
102
- <enum>Qt::Horizontal</enum>
103
- </property>
104
- <property name="sizeType">
105
- <enum>QSizePolicy::Fixed</enum>
106
- </property>
107
- <property name="sizeHint" stdset="0">
108
- <size>
109
- <width>20</width>
110
- <height>20</height>
111
- </size>
112
- </property>
113
- </spacer>
114
- </item>
115
- </layout>
116
- </widget>
117
- <widget class="QStatusBar" name="statusbar"/>
118
- </widget>
119
- <resources/>
120
- <connections/>
121
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/newendonuclease.ui DELETED
@@ -1,816 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>477</width>
10
- <height>742</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="3" column="1">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="1">
40
- <layout class="QGridLayout" name="gridLayout">
41
- <item row="0" column="0">
42
- <layout class="QVBoxLayout" name="verticalLayout">
43
- <item>
44
- <layout class="QGridLayout" name="gridLayout_12">
45
- <item row="0" column="0">
46
- <widget class="QLabel" name="title">
47
- <property name="sizePolicy">
48
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
49
- <horstretch>0</horstretch>
50
- <verstretch>0</verstretch>
51
- </sizepolicy>
52
- </property>
53
- <property name="text">
54
- <string>Define New Endonuclease</string>
55
- </property>
56
- <property name="alignment">
57
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
58
- </property>
59
- </widget>
60
- </item>
61
- <item row="0" column="1" alignment="Qt::AlignRight">
62
- <widget class="QLabel" name="label_9">
63
- <property name="text">
64
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;* Required&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
65
- </property>
66
- </widget>
67
- </item>
68
- <item row="1" column="0" colspan="2">
69
- <widget class="Line" name="line">
70
- <property name="orientation">
71
- <enum>Qt::Horizontal</enum>
72
- </property>
73
- </widget>
74
- </item>
75
- </layout>
76
- </item>
77
- <item>
78
- <widget class="QGroupBox" name="groupBox">
79
- <property name="title">
80
- <string>Cas Details</string>
81
- </property>
82
- <layout class="QGridLayout" name="gridLayout_9">
83
- <item row="2" column="0">
84
- <layout class="QGridLayout" name="gridLayout_8">
85
- <item row="0" column="0">
86
- <layout class="QGridLayout" name="gridLayout_6">
87
- <item row="1" column="2">
88
- <spacer name="horizontalSpacer_11">
89
- <property name="orientation">
90
- <enum>Qt::Horizontal</enum>
91
- </property>
92
- <property name="sizeType">
93
- <enum>QSizePolicy::Fixed</enum>
94
- </property>
95
- <property name="sizeHint" stdset="0">
96
- <size>
97
- <width>10</width>
98
- <height>10</height>
99
- </size>
100
- </property>
101
- </spacer>
102
- </item>
103
- <item row="2" column="3">
104
- <widget class="QLineEdit" name="crispr_type">
105
- <property name="placeholderText">
106
- <string>Ex. II-A</string>
107
- </property>
108
- </widget>
109
- </item>
110
- <item row="1" column="3">
111
- <widget class="QLineEdit" name="abbreviation">
112
- <property name="placeholderText">
113
- <string>Ex. spCas9</string>
114
- </property>
115
- </widget>
116
- </item>
117
- <item row="0" column="1">
118
- <widget class="QLabel" name="label_3">
119
- <property name="sizePolicy">
120
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
121
- <horstretch>0</horstretch>
122
- <verstretch>0</verstretch>
123
- </sizepolicy>
124
- </property>
125
- <property name="toolTip">
126
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Full name of the endonuclease. Ex. &lt;span style=&quot; font-style:italic;&quot;&gt;Streptococcus pyogenes &lt;/span&gt;Cas9 (&lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt; underscores and slashes are not allowed)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
127
- </property>
128
- <property name="text">
129
- <string>Organism: </string>
130
- </property>
131
- </widget>
132
- </item>
133
- <item row="2" column="1">
134
- <widget class="QLabel" name="label">
135
- <property name="sizePolicy">
136
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
137
- <horstretch>0</horstretch>
138
- <verstretch>0</verstretch>
139
- </sizepolicy>
140
- </property>
141
- <property name="toolTip">
142
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;The CRISPR classification that the new endonuclease belongs to. Ex. spCas9's CRISPR type is II-A.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
143
- </property>
144
- <property name="text">
145
- <string>CRISPR Type: </string>
146
- </property>
147
- </widget>
148
- </item>
149
- <item row="1" column="1">
150
- <widget class="QLabel" name="label_2">
151
- <property name="sizePolicy">
152
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
153
- <horstretch>0</horstretch>
154
- <verstretch>0</verstretch>
155
- </sizepolicy>
156
- </property>
157
- <property name="toolTip">
158
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Abbreviated name of new endonuclease, must be unique from existing endonucleases in order for CASPER to recognize it. Ex. spCas9 (&lt;span style=&quot; font-weight:600;&quot;&gt;Note: &lt;/span&gt;underscores, spaces, and slashes are not allowed)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
159
- </property>
160
- <property name="text">
161
- <string>Abbreviation: </string>
162
- </property>
163
- </widget>
164
- </item>
165
- <item row="0" column="3">
166
- <widget class="QLineEdit" name="organism_name">
167
- <property name="placeholderText">
168
- <string>Ex. Streptococcus pyogenes</string>
169
- </property>
170
- </widget>
171
- </item>
172
- <item row="0" column="2">
173
- <spacer name="horizontalSpacer_10">
174
- <property name="orientation">
175
- <enum>Qt::Horizontal</enum>
176
- </property>
177
- <property name="sizeType">
178
- <enum>QSizePolicy::Fixed</enum>
179
- </property>
180
- <property name="sizeHint" stdset="0">
181
- <size>
182
- <width>10</width>
183
- <height>10</height>
184
- </size>
185
- </property>
186
- </spacer>
187
- </item>
188
- <item row="2" column="2">
189
- <spacer name="horizontalSpacer_12">
190
- <property name="orientation">
191
- <enum>Qt::Horizontal</enum>
192
- </property>
193
- <property name="sizeType">
194
- <enum>QSizePolicy::Fixed</enum>
195
- </property>
196
- <property name="sizeHint" stdset="0">
197
- <size>
198
- <width>10</width>
199
- <height>10</height>
200
- </size>
201
- </property>
202
- </spacer>
203
- </item>
204
- <item row="0" column="0">
205
- <widget class="QLabel" name="label_10">
206
- <property name="text">
207
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
208
- </property>
209
- </widget>
210
- </item>
211
- <item row="1" column="0">
212
- <widget class="QLabel" name="label_11">
213
- <property name="text">
214
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
215
- </property>
216
- </widget>
217
- </item>
218
- <item row="2" column="0">
219
- <widget class="QLabel" name="label_14">
220
- <property name="text">
221
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
222
- </property>
223
- </widget>
224
- </item>
225
- </layout>
226
- </item>
227
- </layout>
228
- </item>
229
- <item row="0" column="0">
230
- <spacer name="verticalSpacer_3">
231
- <property name="orientation">
232
- <enum>Qt::Vertical</enum>
233
- </property>
234
- <property name="sizeType">
235
- <enum>QSizePolicy::Fixed</enum>
236
- </property>
237
- <property name="sizeHint" stdset="0">
238
- <size>
239
- <width>10</width>
240
- <height>10</height>
241
- </size>
242
- </property>
243
- </spacer>
244
- </item>
245
- <item row="3" column="0">
246
- <spacer name="verticalSpacer_4">
247
- <property name="orientation">
248
- <enum>Qt::Vertical</enum>
249
- </property>
250
- <property name="sizeType">
251
- <enum>QSizePolicy::Fixed</enum>
252
- </property>
253
- <property name="sizeHint" stdset="0">
254
- <size>
255
- <width>10</width>
256
- <height>10</height>
257
- </size>
258
- </property>
259
- </spacer>
260
- </item>
261
- </layout>
262
- </widget>
263
- </item>
264
- <item>
265
- <widget class="QGroupBox" name="groupBox_2">
266
- <property name="title">
267
- <string>gRNA Details</string>
268
- </property>
269
- <layout class="QGridLayout" name="gridLayout_10">
270
- <item row="1" column="0">
271
- <layout class="QGridLayout" name="gridLayout_7">
272
- <item row="0" column="0">
273
- <layout class="QGridLayout" name="gridLayout_5">
274
- <item row="1" column="2">
275
- <spacer name="horizontalSpacer_6">
276
- <property name="orientation">
277
- <enum>Qt::Horizontal</enum>
278
- </property>
279
- <property name="sizeType">
280
- <enum>QSizePolicy::Fixed</enum>
281
- </property>
282
- <property name="sizeHint" stdset="0">
283
- <size>
284
- <width>10</width>
285
- <height>10</height>
286
- </size>
287
- </property>
288
- </spacer>
289
- </item>
290
- <item row="0" column="3">
291
- <widget class="QLineEdit" name="seed_length">
292
- <property name="placeholderText">
293
- <string>Ex. 16</string>
294
- </property>
295
- </widget>
296
- </item>
297
- <item row="2" column="3">
298
- <widget class="QLineEdit" name="three_length">
299
- <property name="placeholderText">
300
- <string>Ex. 0</string>
301
- </property>
302
- </widget>
303
- </item>
304
- <item row="1" column="1">
305
- <widget class="QLabel" name="label_6">
306
- <property name="sizePolicy">
307
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
308
- <horstretch>0</horstretch>
309
- <verstretch>0</verstretch>
310
- </sizepolicy>
311
- </property>
312
- <property name="toolTip">
313
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Length in nt of gRNA sequence upstream (5’) of the seed sequence.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
314
- </property>
315
- <property name="text">
316
- <string>5' Length:</string>
317
- </property>
318
- </widget>
319
- </item>
320
- <item row="4" column="3">
321
- <layout class="QHBoxLayout" name="horizontalLayout_11">
322
- <item>
323
- <widget class="QRadioButton" name="three_pam">
324
- <property name="sizePolicy">
325
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
326
- <horstretch>0</horstretch>
327
- <verstretch>0</verstretch>
328
- </sizepolicy>
329
- </property>
330
- <property name="text">
331
- <string>3' PAM</string>
332
- </property>
333
- <property name="checked">
334
- <bool>true</bool>
335
- </property>
336
- </widget>
337
- </item>
338
- <item>
339
- <widget class="QRadioButton" name="five_pam">
340
- <property name="sizePolicy">
341
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
342
- <horstretch>0</horstretch>
343
- <verstretch>0</verstretch>
344
- </sizepolicy>
345
- </property>
346
- <property name="text">
347
- <string>5' PAM</string>
348
- </property>
349
- </widget>
350
- </item>
351
- </layout>
352
- </item>
353
- <item row="2" column="1">
354
- <widget class="QLabel" name="label_5">
355
- <property name="sizePolicy">
356
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
357
- <horstretch>0</horstretch>
358
- <verstretch>0</verstretch>
359
- </sizepolicy>
360
- </property>
361
- <property name="toolTip">
362
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Length in nt of gRNA sequence downstream (3’) of the seed sequence.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
363
- </property>
364
- <property name="text">
365
- <string>3' Length:</string>
366
- </property>
367
- </widget>
368
- </item>
369
- <item row="1" column="3">
370
- <widget class="QLineEdit" name="five_length">
371
- <property name="placeholderText">
372
- <string>Ex. 4</string>
373
- </property>
374
- </widget>
375
- </item>
376
- <item row="3" column="3">
377
- <widget class="QLineEdit" name="pam_sequence">
378
- <property name="placeholderText">
379
- <string>Ex. NGG</string>
380
- </property>
381
- </widget>
382
- </item>
383
- <item row="4" column="1">
384
- <widget class="QLabel" name="label_8">
385
- <property name="toolTip">
386
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;End of the gRNA that is adjacent to PAM. Ex. spCas9 has a 3' PAM and AsCas12 has a 5' PAM.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
387
- </property>
388
- <property name="text">
389
- <string>PAM Directionality:</string>
390
- </property>
391
- </widget>
392
- </item>
393
- <item row="0" column="1">
394
- <widget class="QLabel" name="label_7">
395
- <property name="sizePolicy">
396
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
397
- <horstretch>0</horstretch>
398
- <verstretch>0</verstretch>
399
- </sizepolicy>
400
- </property>
401
- <property name="toolTip">
402
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-family:'CMR12'; font-size:12pt;&quot;&gt;Length in nucleotides (nt) of the gRNA region in which binding is most crucial for Cas activity. CASPER’s SeqFinder algorithm uses this seed length and the endonuclease-specific PAM to search for repeated gRNAs across the genome of interest. &lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
403
- </property>
404
- <property name="text">
405
- <string>Seed Length:</string>
406
- </property>
407
- </widget>
408
- </item>
409
- <item row="3" column="1">
410
- <widget class="QLabel" name="label_4">
411
- <property name="sizePolicy">
412
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
413
- <horstretch>0</horstretch>
414
- <verstretch>0</verstretch>
415
- </sizepolicy>
416
- </property>
417
- <property name="toolTip">
418
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;PAM sequence for the new endonuclease. All IUPAC nucleotide codes are accepted, such as V (A, C, or G) or N (A, T, C, or G). For multiple PAM sites, please separate by commas.&lt;/p&gt;&lt;p&gt;Ex. &amp;quot;NGG&amp;quot; or &amp;quot;NNG&amp;quot; for spCas9.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
419
- </property>
420
- <property name="text">
421
- <string>PAM Sequence:</string>
422
- </property>
423
- </widget>
424
- </item>
425
- <item row="0" column="2">
426
- <spacer name="horizontalSpacer_5">
427
- <property name="orientation">
428
- <enum>Qt::Horizontal</enum>
429
- </property>
430
- <property name="sizeType">
431
- <enum>QSizePolicy::Fixed</enum>
432
- </property>
433
- <property name="sizeHint" stdset="0">
434
- <size>
435
- <width>10</width>
436
- <height>10</height>
437
- </size>
438
- </property>
439
- </spacer>
440
- </item>
441
- <item row="2" column="2">
442
- <spacer name="horizontalSpacer_7">
443
- <property name="orientation">
444
- <enum>Qt::Horizontal</enum>
445
- </property>
446
- <property name="sizeType">
447
- <enum>QSizePolicy::Fixed</enum>
448
- </property>
449
- <property name="sizeHint" stdset="0">
450
- <size>
451
- <width>10</width>
452
- <height>10</height>
453
- </size>
454
- </property>
455
- </spacer>
456
- </item>
457
- <item row="3" column="2">
458
- <spacer name="horizontalSpacer_8">
459
- <property name="orientation">
460
- <enum>Qt::Horizontal</enum>
461
- </property>
462
- <property name="sizeType">
463
- <enum>QSizePolicy::Fixed</enum>
464
- </property>
465
- <property name="sizeHint" stdset="0">
466
- <size>
467
- <width>10</width>
468
- <height>10</height>
469
- </size>
470
- </property>
471
- </spacer>
472
- </item>
473
- <item row="4" column="2">
474
- <spacer name="horizontalSpacer_9">
475
- <property name="orientation">
476
- <enum>Qt::Horizontal</enum>
477
- </property>
478
- <property name="sizeType">
479
- <enum>QSizePolicy::Fixed</enum>
480
- </property>
481
- <property name="sizeHint" stdset="0">
482
- <size>
483
- <width>10</width>
484
- <height>10</height>
485
- </size>
486
- </property>
487
- </spacer>
488
- </item>
489
- <item row="0" column="0">
490
- <widget class="QLabel" name="label_15">
491
- <property name="text">
492
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
493
- </property>
494
- </widget>
495
- </item>
496
- <item row="1" column="0">
497
- <widget class="QLabel" name="label_16">
498
- <property name="text">
499
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
500
- </property>
501
- </widget>
502
- </item>
503
- <item row="2" column="0">
504
- <widget class="QLabel" name="label_17">
505
- <property name="text">
506
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
507
- </property>
508
- </widget>
509
- </item>
510
- <item row="3" column="0">
511
- <widget class="QLabel" name="label_18">
512
- <property name="text">
513
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
514
- </property>
515
- </widget>
516
- </item>
517
- <item row="4" column="0">
518
- <widget class="QLabel" name="label_19">
519
- <property name="text">
520
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
521
- </property>
522
- </widget>
523
- </item>
524
- </layout>
525
- </item>
526
- </layout>
527
- </item>
528
- <item row="0" column="0">
529
- <spacer name="verticalSpacer_5">
530
- <property name="orientation">
531
- <enum>Qt::Vertical</enum>
532
- </property>
533
- <property name="sizeType">
534
- <enum>QSizePolicy::Fixed</enum>
535
- </property>
536
- <property name="sizeHint" stdset="0">
537
- <size>
538
- <width>10</width>
539
- <height>10</height>
540
- </size>
541
- </property>
542
- </spacer>
543
- </item>
544
- <item row="2" column="0">
545
- <spacer name="verticalSpacer_6">
546
- <property name="orientation">
547
- <enum>Qt::Vertical</enum>
548
- </property>
549
- <property name="sizeType">
550
- <enum>QSizePolicy::Fixed</enum>
551
- </property>
552
- <property name="sizeHint" stdset="0">
553
- <size>
554
- <width>10</width>
555
- <height>10</height>
556
- </size>
557
- </property>
558
- </spacer>
559
- </item>
560
- </layout>
561
- </widget>
562
- </item>
563
- <item>
564
- <widget class="QGroupBox" name="groupBox_3">
565
- <property name="title">
566
- <string>Scoring Algorithms</string>
567
- </property>
568
- <layout class="QGridLayout" name="gridLayout_11">
569
- <item row="0" column="0">
570
- <spacer name="verticalSpacer_7">
571
- <property name="orientation">
572
- <enum>Qt::Vertical</enum>
573
- </property>
574
- <property name="sizeType">
575
- <enum>QSizePolicy::Fixed</enum>
576
- </property>
577
- <property name="sizeHint" stdset="0">
578
- <size>
579
- <width>10</width>
580
- <height>10</height>
581
- </size>
582
- </property>
583
- </spacer>
584
- </item>
585
- <item row="1" column="0">
586
- <layout class="QGridLayout" name="gridLayout_4">
587
- <item row="0" column="0">
588
- <layout class="QGridLayout" name="gridLayout_3">
589
- <item row="2" column="3">
590
- <widget class="QComboBox" name="comboBox">
591
- <property name="sizePolicy">
592
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
593
- <horstretch>0</horstretch>
594
- <verstretch>0</verstretch>
595
- </sizepolicy>
596
- </property>
597
- </widget>
598
- </item>
599
- <item row="2" column="1">
600
- <widget class="QLabel" name="label_12">
601
- <property name="toolTip">
602
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;On-target scoring matrix. Default is CRISPRscan data.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
603
- </property>
604
- <property name="text">
605
- <string>On-Target Matrix:</string>
606
- </property>
607
- </widget>
608
- </item>
609
- <item row="2" column="2">
610
- <spacer name="horizontalSpacer_3">
611
- <property name="orientation">
612
- <enum>Qt::Horizontal</enum>
613
- </property>
614
- <property name="sizeType">
615
- <enum>QSizePolicy::Fixed</enum>
616
- </property>
617
- <property name="sizeHint" stdset="0">
618
- <size>
619
- <width>10</width>
620
- <height>10</height>
621
- </size>
622
- </property>
623
- </spacer>
624
- </item>
625
- <item row="3" column="1">
626
- <widget class="QLabel" name="label_13">
627
- <property name="toolTip">
628
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Off-target scoring matrix. Default is Hsu matrix data.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
629
- </property>
630
- <property name="text">
631
- <string>Off-Target Matrix:</string>
632
- </property>
633
- </widget>
634
- </item>
635
- <item row="3" column="3">
636
- <widget class="QComboBox" name="comboBox_2">
637
- <property name="sizePolicy">
638
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
639
- <horstretch>0</horstretch>
640
- <verstretch>0</verstretch>
641
- </sizepolicy>
642
- </property>
643
- </widget>
644
- </item>
645
- <item row="3" column="2">
646
- <spacer name="horizontalSpacer_4">
647
- <property name="orientation">
648
- <enum>Qt::Horizontal</enum>
649
- </property>
650
- <property name="sizeType">
651
- <enum>QSizePolicy::Fixed</enum>
652
- </property>
653
- <property name="sizeHint" stdset="0">
654
- <size>
655
- <width>10</width>
656
- <height>10</height>
657
- </size>
658
- </property>
659
- </spacer>
660
- </item>
661
- <item row="2" column="0">
662
- <widget class="QLabel" name="label_20">
663
- <property name="text">
664
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
665
- </property>
666
- </widget>
667
- </item>
668
- <item row="3" column="0">
669
- <widget class="QLabel" name="label_21">
670
- <property name="text">
671
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#fc0107;&quot;&gt;*&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
672
- </property>
673
- </widget>
674
- </item>
675
- </layout>
676
- </item>
677
- </layout>
678
- </item>
679
- <item row="2" column="0">
680
- <spacer name="verticalSpacer_8">
681
- <property name="orientation">
682
- <enum>Qt::Vertical</enum>
683
- </property>
684
- <property name="sizeType">
685
- <enum>QSizePolicy::Fixed</enum>
686
- </property>
687
- <property name="sizeHint" stdset="0">
688
- <size>
689
- <width>10</width>
690
- <height>10</height>
691
- </size>
692
- </property>
693
- </spacer>
694
- </item>
695
- </layout>
696
- </widget>
697
- </item>
698
- </layout>
699
- </item>
700
- </layout>
701
- </item>
702
- <item row="0" column="1">
703
- <spacer name="verticalSpacer_2">
704
- <property name="orientation">
705
- <enum>Qt::Vertical</enum>
706
- </property>
707
- <property name="sizeType">
708
- <enum>QSizePolicy::Fixed</enum>
709
- </property>
710
- <property name="sizeHint" stdset="0">
711
- <size>
712
- <width>20</width>
713
- <height>20</height>
714
- </size>
715
- </property>
716
- </spacer>
717
- </item>
718
- <item row="1" column="2">
719
- <spacer name="horizontalSpacer_2">
720
- <property name="orientation">
721
- <enum>Qt::Horizontal</enum>
722
- </property>
723
- <property name="sizeType">
724
- <enum>QSizePolicy::Fixed</enum>
725
- </property>
726
- <property name="sizeHint" stdset="0">
727
- <size>
728
- <width>20</width>
729
- <height>20</height>
730
- </size>
731
- </property>
732
- </spacer>
733
- </item>
734
- <item row="1" column="0">
735
- <spacer name="horizontalSpacer">
736
- <property name="orientation">
737
- <enum>Qt::Horizontal</enum>
738
- </property>
739
- <property name="sizeType">
740
- <enum>QSizePolicy::Fixed</enum>
741
- </property>
742
- <property name="sizeHint" stdset="0">
743
- <size>
744
- <width>20</width>
745
- <height>20</height>
746
- </size>
747
- </property>
748
- </spacer>
749
- </item>
750
- <item row="2" column="1">
751
- <layout class="QHBoxLayout" name="horizontalLayout_2">
752
- <property name="sizeConstraint">
753
- <enum>QLayout::SetDefaultConstraint</enum>
754
- </property>
755
- <item alignment="Qt::AlignLeft">
756
- <widget class="QPushButton" name="cancel_button">
757
- <property name="sizePolicy">
758
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
759
- <horstretch>0</horstretch>
760
- <verstretch>0</verstretch>
761
- </sizepolicy>
762
- </property>
763
- <property name="minimumSize">
764
- <size>
765
- <width>125</width>
766
- <height>0</height>
767
- </size>
768
- </property>
769
- <property name="text">
770
- <string>Cancel</string>
771
- </property>
772
- </widget>
773
- </item>
774
- <item alignment="Qt::AlignRight">
775
- <widget class="QPushButton" name="submit_button">
776
- <property name="sizePolicy">
777
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
778
- <horstretch>0</horstretch>
779
- <verstretch>0</verstretch>
780
- </sizepolicy>
781
- </property>
782
- <property name="minimumSize">
783
- <size>
784
- <width>125</width>
785
- <height>0</height>
786
- </size>
787
- </property>
788
- <property name="text">
789
- <string>Submit</string>
790
- </property>
791
- </widget>
792
- </item>
793
- </layout>
794
- </item>
795
- </layout>
796
- </widget>
797
- <widget class="QStatusBar" name="statusbar"/>
798
- </widget>
799
- <tabstops>
800
- <tabstop>organism_name</tabstop>
801
- <tabstop>abbreviation</tabstop>
802
- <tabstop>crispr_type</tabstop>
803
- <tabstop>seed_length</tabstop>
804
- <tabstop>five_length</tabstop>
805
- <tabstop>three_length</tabstop>
806
- <tabstop>pam_sequence</tabstop>
807
- <tabstop>three_pam</tabstop>
808
- <tabstop>five_pam</tabstop>
809
- <tabstop>comboBox</tabstop>
810
- <tabstop>comboBox_2</tabstop>
811
- <tabstop>cancel_button</tabstop>
812
- <tabstop>submit_button</tabstop>
813
- </tabstops>
814
- <resources/>
815
- <connections/>
816
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/newgenomenavigationpage.ui DELETED
@@ -1,184 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>860</width>
10
- <height>279</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="2" column="1">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="2">
40
- <spacer name="horizontalSpacer_2">
41
- <property name="orientation">
42
- <enum>Qt::Horizontal</enum>
43
- </property>
44
- <property name="sizeType">
45
- <enum>QSizePolicy::Fixed</enum>
46
- </property>
47
- <property name="sizeHint" stdset="0">
48
- <size>
49
- <width>20</width>
50
- <height>20</height>
51
- </size>
52
- </property>
53
- </spacer>
54
- </item>
55
- <item row="1" column="1">
56
- <layout class="QGridLayout" name="gridLayout">
57
- <item row="0" column="0">
58
- <widget class="QGroupBox" name="groupBox">
59
- <property name="toolTip">
60
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select an analysis option or close this window to analyze more genomes.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
61
- </property>
62
- <property name="title">
63
- <string>Analyze New Genome:</string>
64
- </property>
65
- <layout class="QHBoxLayout" name="horizontalLayout_2">
66
- <item>
67
- <layout class="QHBoxLayout" name="horizontalLayout">
68
- <item>
69
- <spacer name="horizontalSpacer_3">
70
- <property name="orientation">
71
- <enum>Qt::Horizontal</enum>
72
- </property>
73
- <property name="sizeType">
74
- <enum>QSizePolicy::Fixed</enum>
75
- </property>
76
- <property name="sizeHint" stdset="0">
77
- <size>
78
- <width>10</width>
79
- <height>10</height>
80
- </size>
81
- </property>
82
- </spacer>
83
- </item>
84
- <item>
85
- <widget class="QPushButton" name="goToMain">
86
- <property name="sizePolicy">
87
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
88
- <horstretch>0</horstretch>
89
- <verstretch>0</verstretch>
90
- </sizepolicy>
91
- </property>
92
- <property name="text">
93
- <string>Main</string>
94
- </property>
95
- </widget>
96
- </item>
97
- <item>
98
- <widget class="QPushButton" name="goToMT">
99
- <property name="sizePolicy">
100
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
101
- <horstretch>0</horstretch>
102
- <verstretch>0</verstretch>
103
- </sizepolicy>
104
- </property>
105
- <property name="text">
106
- <string>Multitargeting Analysis</string>
107
- </property>
108
- </widget>
109
- </item>
110
- <item>
111
- <widget class="QPushButton" name="goToPop">
112
- <property name="sizePolicy">
113
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
114
- <horstretch>0</horstretch>
115
- <verstretch>0</verstretch>
116
- </sizepolicy>
117
- </property>
118
- <property name="text">
119
- <string>Population Analysis</string>
120
- </property>
121
- </widget>
122
- </item>
123
- <item>
124
- <spacer name="horizontalSpacer_4">
125
- <property name="orientation">
126
- <enum>Qt::Horizontal</enum>
127
- </property>
128
- <property name="sizeType">
129
- <enum>QSizePolicy::Fixed</enum>
130
- </property>
131
- <property name="sizeHint" stdset="0">
132
- <size>
133
- <width>10</width>
134
- <height>10</height>
135
- </size>
136
- </property>
137
- </spacer>
138
- </item>
139
- </layout>
140
- </item>
141
- </layout>
142
- </widget>
143
- </item>
144
- </layout>
145
- </item>
146
- <item row="1" column="0">
147
- <spacer name="horizontalSpacer">
148
- <property name="orientation">
149
- <enum>Qt::Horizontal</enum>
150
- </property>
151
- <property name="sizeType">
152
- <enum>QSizePolicy::Fixed</enum>
153
- </property>
154
- <property name="sizeHint" stdset="0">
155
- <size>
156
- <width>20</width>
157
- <height>20</height>
158
- </size>
159
- </property>
160
- </spacer>
161
- </item>
162
- <item row="0" column="1">
163
- <spacer name="verticalSpacer_2">
164
- <property name="orientation">
165
- <enum>Qt::Vertical</enum>
166
- </property>
167
- <property name="sizeType">
168
- <enum>QSizePolicy::Fixed</enum>
169
- </property>
170
- <property name="sizeHint" stdset="0">
171
- <size>
172
- <width>20</width>
173
- <height>20</height>
174
- </size>
175
- </property>
176
- </spacer>
177
- </item>
178
- </layout>
179
- </widget>
180
- <widget class="QStatusBar" name="statusbar"/>
181
- </widget>
182
- <resources/>
183
- <connections/>
184
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/off_target.ui DELETED
@@ -1,394 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>tolerancelineEdit</class>
4
- <widget class="QMainWindow" name="tolerancelineEdit">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>455</width>
10
- <height>656</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="1" column="1">
24
- <layout class="QGridLayout" name="gridLayout">
25
- <item row="2" column="0" colspan="2">
26
- <widget class="QGroupBox" name="Step1">
27
- <property name="title">
28
- <string>Step 1: Select References</string>
29
- </property>
30
- <layout class="QGridLayout" name="gridLayout_4">
31
- <item row="2" column="1">
32
- <widget class="QComboBox" name="EndocomboBox">
33
- <property name="sizePolicy">
34
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
35
- <horstretch>0</horstretch>
36
- <verstretch>0</verstretch>
37
- </sizepolicy>
38
- </property>
39
- </widget>
40
- </item>
41
- <item row="1" column="0">
42
- <widget class="QLabel" name="label_2">
43
- <property name="toolTip">
44
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;This is the reference organism that off-target will be ran against. List is populated based on currenet CSPR files in CASPER database directory.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
45
- </property>
46
- <property name="text">
47
- <string>Organism:</string>
48
- </property>
49
- </widget>
50
- </item>
51
- <item row="1" column="1">
52
- <widget class="QComboBox" name="OrgcomboBox">
53
- <property name="sizePolicy">
54
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
55
- <horstretch>0</horstretch>
56
- <verstretch>0</verstretch>
57
- </sizepolicy>
58
- </property>
59
- </widget>
60
- </item>
61
- <item row="0" column="0" colspan="2">
62
- <spacer name="verticalSpacer_3">
63
- <property name="orientation">
64
- <enum>Qt::Vertical</enum>
65
- </property>
66
- <property name="sizeType">
67
- <enum>QSizePolicy::Preferred</enum>
68
- </property>
69
- <property name="sizeHint" stdset="0">
70
- <size>
71
- <width>20</width>
72
- <height>10</height>
73
- </size>
74
- </property>
75
- </spacer>
76
- </item>
77
- <item row="2" column="0">
78
- <widget class="QLabel" name="label_3">
79
- <property name="toolTip">
80
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;This is the reference endonuclease that will be used for off-target analysis.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
81
- </property>
82
- <property name="text">
83
- <string>Endonuclease:</string>
84
- </property>
85
- </widget>
86
- </item>
87
- <item row="3" column="0" colspan="2">
88
- <spacer name="verticalSpacer_7">
89
- <property name="orientation">
90
- <enum>Qt::Vertical</enum>
91
- </property>
92
- <property name="sizeType">
93
- <enum>QSizePolicy::Preferred</enum>
94
- </property>
95
- <property name="sizeHint" stdset="0">
96
- <size>
97
- <width>20</width>
98
- <height>10</height>
99
- </size>
100
- </property>
101
- </spacer>
102
- </item>
103
- </layout>
104
- </widget>
105
- </item>
106
- <item row="3" column="0" colspan="2">
107
- <widget class="QGroupBox" name="Step2">
108
- <property name="title">
109
- <string>Step 2: Set Parameters</string>
110
- </property>
111
- <layout class="QGridLayout" name="gridLayout_5">
112
- <item row="1" column="2">
113
- <widget class="QDoubleSpinBox" name="toleranceSpinBox">
114
- <property name="maximum">
115
- <double>0.500000000000000</double>
116
- </property>
117
- <property name="singleStep">
118
- <double>0.050000000000000</double>
119
- </property>
120
- <property name="value">
121
- <double>0.050000000000000</double>
122
- </property>
123
- </widget>
124
- </item>
125
- <item row="2" column="2">
126
- <widget class="QComboBox" name="mismatchcomboBox"/>
127
- </item>
128
- <item row="5" column="0">
129
- <widget class="QLabel" name="label">
130
- <property name="text">
131
- <string>Save Output File?</string>
132
- </property>
133
- </widget>
134
- </item>
135
- <item row="0" column="0" colspan="3">
136
- <spacer name="verticalSpacer_4">
137
- <property name="orientation">
138
- <enum>Qt::Vertical</enum>
139
- </property>
140
- <property name="sizeType">
141
- <enum>QSizePolicy::Preferred</enum>
142
- </property>
143
- <property name="sizeHint" stdset="0">
144
- <size>
145
- <width>20</width>
146
- <height>10</height>
147
- </size>
148
- </property>
149
- </spacer>
150
- </item>
151
- <item row="6" column="0" colspan="3">
152
- <spacer name="verticalSpacer_6">
153
- <property name="orientation">
154
- <enum>Qt::Vertical</enum>
155
- </property>
156
- <property name="sizeType">
157
- <enum>QSizePolicy::Preferred</enum>
158
- </property>
159
- <property name="sizeHint" stdset="0">
160
- <size>
161
- <width>20</width>
162
- <height>10</height>
163
- </size>
164
- </property>
165
- </spacer>
166
- </item>
167
- <item row="1" column="0">
168
- <widget class="QLabel" name="label_4">
169
- <property name="toolTip">
170
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Potential off-target sites scoring lower than this value are dismissed (I.e. they do not pose a threat for off-target activity). Computational time increases as tolerance value decreases.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
171
- </property>
172
- <property name="text">
173
- <string>Tolerance:</string>
174
- </property>
175
- </widget>
176
- </item>
177
- <item row="3" column="0">
178
- <widget class="QLabel" name="label_6">
179
- <property name="toolTip">
180
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check this option if you only want to see the average off-target score for each gRNA. Leaving this option unchecked will report the average off-target score as well as the putatitve off-target sequences, their locations, and individual off-target scores.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
181
- </property>
182
- <property name="text">
183
- <string>Average Output</string>
184
- </property>
185
- </widget>
186
- </item>
187
- <item row="3" column="2">
188
- <widget class="QCheckBox" name="AVG">
189
- <property name="text">
190
- <string/>
191
- </property>
192
- </widget>
193
- </item>
194
- <item row="2" column="0">
195
- <widget class="QLabel" name="label_5">
196
- <property name="toolTip">
197
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If the number of mismatches in a putative off-target site exceeds this number, CASPER will not score the site. Computational time increases as this number increases.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
198
- </property>
199
- <property name="text">
200
- <string>Max No. Mismatches:</string>
201
- </property>
202
- </widget>
203
- </item>
204
- <item row="5" column="1">
205
- <widget class="QCheckBox" name="outputCheckBox">
206
- <property name="text">
207
- <string>No</string>
208
- </property>
209
- </widget>
210
- </item>
211
- <item row="5" column="2">
212
- <widget class="QLineEdit" name="outputFileName">
213
- <property name="placeholderText">
214
- <string>Yes. Name the file.</string>
215
- </property>
216
- </widget>
217
- </item>
218
- </layout>
219
- </widget>
220
- </item>
221
- <item row="5" column="1" alignment="Qt::AlignRight">
222
- <widget class="QPushButton" name="submitButton">
223
- <property name="minimumSize">
224
- <size>
225
- <width>125</width>
226
- <height>0</height>
227
- </size>
228
- </property>
229
- <property name="text">
230
- <string>Submit</string>
231
- </property>
232
- </widget>
233
- </item>
234
- <item row="1" column="0" colspan="2">
235
- <widget class="Line" name="line">
236
- <property name="orientation">
237
- <enum>Qt::Horizontal</enum>
238
- </property>
239
- </widget>
240
- </item>
241
- <item row="4" column="0" colspan="2">
242
- <widget class="QGroupBox" name="Step3">
243
- <property name="title">
244
- <string>Step 3: Run Off-Target</string>
245
- </property>
246
- <layout class="QGridLayout" name="gridLayout_6">
247
- <item row="1" column="0">
248
- <widget class="QPushButton" name="Run">
249
- <property name="text">
250
- <string>Run</string>
251
- </property>
252
- </widget>
253
- </item>
254
- <item row="3" column="0">
255
- <widget class="QProgressBar" name="progressBar">
256
- <property name="value">
257
- <number>24</number>
258
- </property>
259
- </widget>
260
- </item>
261
- <item row="0" column="0">
262
- <spacer name="verticalSpacer_5">
263
- <property name="orientation">
264
- <enum>Qt::Vertical</enum>
265
- </property>
266
- <property name="sizeType">
267
- <enum>QSizePolicy::Preferred</enum>
268
- </property>
269
- <property name="sizeHint" stdset="0">
270
- <size>
271
- <width>20</width>
272
- <height>10</height>
273
- </size>
274
- </property>
275
- </spacer>
276
- </item>
277
- <item row="4" column="0">
278
- <spacer name="verticalSpacer_8">
279
- <property name="orientation">
280
- <enum>Qt::Vertical</enum>
281
- </property>
282
- <property name="sizeType">
283
- <enum>QSizePolicy::Preferred</enum>
284
- </property>
285
- <property name="sizeHint" stdset="0">
286
- <size>
287
- <width>20</width>
288
- <height>10</height>
289
- </size>
290
- </property>
291
- </spacer>
292
- </item>
293
- </layout>
294
- </widget>
295
- </item>
296
- <item row="0" column="0" colspan="2">
297
- <widget class="QLabel" name="title">
298
- <property name="sizePolicy">
299
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
300
- <horstretch>0</horstretch>
301
- <verstretch>0</verstretch>
302
- </sizepolicy>
303
- </property>
304
- <property name="text">
305
- <string>Off-Target Analysis</string>
306
- </property>
307
- </widget>
308
- </item>
309
- <item row="5" column="0" alignment="Qt::AlignLeft">
310
- <widget class="QPushButton" name="cancelButton">
311
- <property name="minimumSize">
312
- <size>
313
- <width>125</width>
314
- <height>0</height>
315
- </size>
316
- </property>
317
- <property name="text">
318
- <string>Cancel</string>
319
- </property>
320
- </widget>
321
- </item>
322
- </layout>
323
- </item>
324
- <item row="2" column="1">
325
- <spacer name="verticalSpacer">
326
- <property name="orientation">
327
- <enum>Qt::Vertical</enum>
328
- </property>
329
- <property name="sizeType">
330
- <enum>QSizePolicy::Fixed</enum>
331
- </property>
332
- <property name="sizeHint" stdset="0">
333
- <size>
334
- <width>20</width>
335
- <height>20</height>
336
- </size>
337
- </property>
338
- </spacer>
339
- </item>
340
- <item row="1" column="2">
341
- <spacer name="horizontalSpacer_2">
342
- <property name="orientation">
343
- <enum>Qt::Horizontal</enum>
344
- </property>
345
- <property name="sizeType">
346
- <enum>QSizePolicy::Fixed</enum>
347
- </property>
348
- <property name="sizeHint" stdset="0">
349
- <size>
350
- <width>20</width>
351
- <height>20</height>
352
- </size>
353
- </property>
354
- </spacer>
355
- </item>
356
- <item row="1" column="0">
357
- <spacer name="horizontalSpacer">
358
- <property name="orientation">
359
- <enum>Qt::Horizontal</enum>
360
- </property>
361
- <property name="sizeType">
362
- <enum>QSizePolicy::Fixed</enum>
363
- </property>
364
- <property name="sizeHint" stdset="0">
365
- <size>
366
- <width>20</width>
367
- <height>20</height>
368
- </size>
369
- </property>
370
- </spacer>
371
- </item>
372
- <item row="0" column="1">
373
- <spacer name="verticalSpacer_2">
374
- <property name="orientation">
375
- <enum>Qt::Vertical</enum>
376
- </property>
377
- <property name="sizeType">
378
- <enum>QSizePolicy::Fixed</enum>
379
- </property>
380
- <property name="sizeHint" stdset="0">
381
- <size>
382
- <width>20</width>
383
- <height>20</height>
384
- </size>
385
- </property>
386
- </spacer>
387
- </item>
388
- </layout>
389
- </widget>
390
- <widget class="QStatusBar" name="statusbar"/>
391
- </widget>
392
- <resources/>
393
- <connections/>
394
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/pop.ui DELETED
@@ -1,425 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>973</width>
10
- <height>829</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="0" column="1">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="1" column="1">
40
- <layout class="QGridLayout" name="gridLayout">
41
- <item row="2" column="0" rowspan="2">
42
- <widget class="QGroupBox" name="groupBox">
43
- <property name="sizePolicy">
44
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
45
- <horstretch>0</horstretch>
46
- <verstretch>0</verstretch>
47
- </sizepolicy>
48
- </property>
49
- <property name="maximumSize">
50
- <size>
51
- <width>600</width>
52
- <height>16777215</height>
53
- </size>
54
- </property>
55
- <property name="toolTip">
56
- <string>Please select organism(s) and an endonuclease, and click &quot;Analyze Organism(s)&quot; to populate the population analysis window.</string>
57
- </property>
58
- <property name="title">
59
- <string>Select Organism(s) and Endonuclease:</string>
60
- </property>
61
- <layout class="QGridLayout" name="gridLayout_6">
62
- <item row="3" column="0" colspan="2">
63
- <widget class="QPushButton" name="analyze_button">
64
- <property name="font">
65
- <font>
66
- <weight>75</weight>
67
- <bold>true</bold>
68
- </font>
69
- </property>
70
- <property name="text">
71
- <string>Analyze Organism(s)</string>
72
- </property>
73
- </widget>
74
- </item>
75
- <item row="0" column="0" colspan="2">
76
- <spacer name="verticalSpacer_3">
77
- <property name="orientation">
78
- <enum>Qt::Vertical</enum>
79
- </property>
80
- <property name="sizeType">
81
- <enum>QSizePolicy::Fixed</enum>
82
- </property>
83
- <property name="sizeHint" stdset="0">
84
- <size>
85
- <width>10</width>
86
- <height>10</height>
87
- </size>
88
- </property>
89
- </spacer>
90
- </item>
91
- <item row="1" column="1">
92
- <widget class="QComboBox" name="endoBox">
93
- <property name="sizePolicy">
94
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
95
- <horstretch>0</horstretch>
96
- <verstretch>0</verstretch>
97
- </sizepolicy>
98
- </property>
99
- </widget>
100
- </item>
101
- <item row="2" column="0" colspan="2">
102
- <widget class="QTableWidget" name="org_Table">
103
- <property name="sizePolicy">
104
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
105
- <horstretch>0</horstretch>
106
- <verstretch>0</verstretch>
107
- </sizepolicy>
108
- </property>
109
- <property name="minimumSize">
110
- <size>
111
- <width>0</width>
112
- <height>225</height>
113
- </size>
114
- </property>
115
- </widget>
116
- </item>
117
- <item row="1" column="0">
118
- <widget class="QLabel" name="label">
119
- <property name="sizePolicy">
120
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
121
- <horstretch>0</horstretch>
122
- <verstretch>0</verstretch>
123
- </sizepolicy>
124
- </property>
125
- <property name="text">
126
- <string>Endonuclease:</string>
127
- </property>
128
- </widget>
129
- </item>
130
- <item row="4" column="0" colspan="2">
131
- <widget class="QTabWidget" name="tabWidget">
132
- <property name="sizePolicy">
133
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
134
- <horstretch>0</horstretch>
135
- <verstretch>0</verstretch>
136
- </sizepolicy>
137
- </property>
138
- <property name="minimumSize">
139
- <size>
140
- <width>0</width>
141
- <height>225</height>
142
- </size>
143
- </property>
144
- <property name="toolTip">
145
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Heatmap of shared repeats between all selected organisms. Diagonals show number of self-contained repeats. Axis labels correspond to the rows of the organism selection table.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
146
- </property>
147
- <property name="currentIndex">
148
- <number>0</number>
149
- </property>
150
- <widget class="QWidget" name="tab">
151
- <attribute name="title">
152
- <string>Shared Seed Heatmap</string>
153
- </attribute>
154
- <layout class="QGridLayout" name="gridLayout_3">
155
- <item row="0" column="0">
156
- <widget class="QWidget" name="colormap_figure" native="true"/>
157
- </item>
158
- </layout>
159
- </widget>
160
- </widget>
161
- </item>
162
- <item row="5" column="0" colspan="2">
163
- <spacer name="verticalSpacer_4">
164
- <property name="orientation">
165
- <enum>Qt::Vertical</enum>
166
- </property>
167
- <property name="sizeType">
168
- <enum>QSizePolicy::Fixed</enum>
169
- </property>
170
- <property name="sizeHint" stdset="0">
171
- <size>
172
- <width>10</width>
173
- <height>10</height>
174
- </size>
175
- </property>
176
- </spacer>
177
- </item>
178
- </layout>
179
- </widget>
180
- </item>
181
- <item row="4" column="0" alignment="Qt::AlignLeft">
182
- <widget class="QPushButton" name="goBackButton">
183
- <property name="minimumSize">
184
- <size>
185
- <width>125</width>
186
- <height>0</height>
187
- </size>
188
- </property>
189
- <property name="text">
190
- <string>Back</string>
191
- </property>
192
- </widget>
193
- </item>
194
- <item row="2" column="1" rowspan="2">
195
- <widget class="QGroupBox" name="groupBox_2">
196
- <property name="sizePolicy">
197
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
198
- <horstretch>0</horstretch>
199
- <verstretch>0</verstretch>
200
- </sizepolicy>
201
- </property>
202
- <property name="toolTip">
203
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;These tables show the seeds that are conserved among &lt;span style=&quot; font-weight:600;&quot;&gt;all &lt;/span&gt;selected organisms.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
204
- </property>
205
- <property name="title">
206
- <string>Seed Analysis:</string>
207
- </property>
208
- <layout class="QGridLayout" name="gridLayout_5">
209
- <item row="4" column="1">
210
- <widget class="QPushButton" name="find_locs_button">
211
- <property name="text">
212
- <string>Find Locations</string>
213
- </property>
214
- </widget>
215
- </item>
216
- <item row="2" column="0">
217
- <widget class="QPushButton" name="query_seed_button">
218
- <property name="text">
219
- <string>Query Seed</string>
220
- </property>
221
- </widget>
222
- </item>
223
- <item row="3" column="0" colspan="3">
224
- <widget class="QTableWidget" name="table2">
225
- <property name="sizePolicy">
226
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
227
- <horstretch>0</horstretch>
228
- <verstretch>0</verstretch>
229
- </sizepolicy>
230
- </property>
231
- <property name="minimumSize">
232
- <size>
233
- <width>0</width>
234
- <height>225</height>
235
- </size>
236
- </property>
237
- <property name="toolTip">
238
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;% Coverage&lt;/span&gt;: percentage of analyzed organisms covered by the given seed sequence. (Ex. a coverage of 75% for an analysis of 4 organisms means that the seed appears in 3/4 of the organisms) &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Total Repeats&lt;/span&gt;: the total number of times the seed sequence is repeated across all organisms analyzed &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Avg. Repeats/Scaffold&lt;/span&gt;: the average number of times the seed sequence is repeated per scaffold/chromosome/contig (varies depending on how the organism’s FASTA file is arranged) &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Consensus Sequence&lt;/span&gt;: the full length guide RNA sequence that appears most commonly amongst all occurrences of the given seed. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;% Consensus&lt;/span&gt;: the percentage of all seed repeats that have the tail of the consensus sequence. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Score&lt;/span&gt;: on-target score for the consensus sequence.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;PAM&lt;/span&gt;: the protospacer adjacent motif of the consensus sequence.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Strand&lt;/span&gt;: the strand directionality (+ or -) of the consensus sequence.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
239
- </property>
240
- </widget>
241
- </item>
242
- <item row="2" column="2">
243
- <widget class="QPushButton" name="clear_Button">
244
- <property name="text">
245
- <string>Clear Seeds</string>
246
- </property>
247
- </widget>
248
- </item>
249
- <item row="1" column="1" colspan="2">
250
- <widget class="QLineEdit" name="seed_input"/>
251
- </item>
252
- <item row="0" column="0" colspan="3">
253
- <spacer name="verticalSpacer_5">
254
- <property name="orientation">
255
- <enum>Qt::Vertical</enum>
256
- </property>
257
- <property name="sizeType">
258
- <enum>QSizePolicy::Fixed</enum>
259
- </property>
260
- <property name="sizeHint" stdset="0">
261
- <size>
262
- <width>10</width>
263
- <height>10</height>
264
- </size>
265
- </property>
266
- </spacer>
267
- </item>
268
- <item row="4" column="2">
269
- <widget class="QPushButton" name="clear_loc_button">
270
- <property name="text">
271
- <string>Clear Locations</string>
272
- </property>
273
- </widget>
274
- </item>
275
- <item row="4" column="0">
276
- <widget class="QLabel" name="label_3">
277
- <property name="toolTip">
278
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Highlight a seed and click &amp;quot;Find Locations&amp;quot; to view the exact location and organism of every repeat belonging to that seed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
279
- </property>
280
- <property name="text">
281
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Location Finder:&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
282
- </property>
283
- </widget>
284
- </item>
285
- <item row="5" column="0" colspan="3">
286
- <widget class="QTableWidget" name="loc_finder_table">
287
- <property name="sizePolicy">
288
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
289
- <horstretch>0</horstretch>
290
- <verstretch>0</verstretch>
291
- </sizepolicy>
292
- </property>
293
- <property name="minimumSize">
294
- <size>
295
- <width>0</width>
296
- <height>225</height>
297
- </size>
298
- </property>
299
- </widget>
300
- </item>
301
- <item row="1" column="0">
302
- <widget class="QLabel" name="label_2">
303
- <property name="sizePolicy">
304
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
305
- <horstretch>0</horstretch>
306
- <verstretch>0</verstretch>
307
- </sizepolicy>
308
- </property>
309
- <property name="text">
310
- <string>Seed Search:</string>
311
- </property>
312
- </widget>
313
- </item>
314
- <item row="6" column="0" colspan="3">
315
- <spacer name="verticalSpacer_6">
316
- <property name="orientation">
317
- <enum>Qt::Vertical</enum>
318
- </property>
319
- <property name="sizeType">
320
- <enum>QSizePolicy::Fixed</enum>
321
- </property>
322
- <property name="sizeHint" stdset="0">
323
- <size>
324
- <width>10</width>
325
- <height>10</height>
326
- </size>
327
- </property>
328
- </spacer>
329
- </item>
330
- </layout>
331
- </widget>
332
- </item>
333
- <item row="4" column="1" alignment="Qt::AlignRight">
334
- <widget class="QPushButton" name="export_button">
335
- <property name="minimumSize">
336
- <size>
337
- <width>175</width>
338
- <height>0</height>
339
- </size>
340
- </property>
341
- <property name="toolTip">
342
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Click to export selected gRNAs. &lt;span style=&quot; font-weight:600;&quot;&gt;Note: &lt;/span&gt;only rows from the first (top right) table can be selected and exported.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
343
- </property>
344
- <property name="text">
345
- <string>Export Selected gRNAs</string>
346
- </property>
347
- </widget>
348
- </item>
349
- <item row="0" column="0" colspan="2">
350
- <widget class="QLabel" name="title">
351
- <property name="sizePolicy">
352
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
353
- <horstretch>0</horstretch>
354
- <verstretch>0</verstretch>
355
- </sizepolicy>
356
- </property>
357
- <property name="text">
358
- <string>Population Analysis</string>
359
- </property>
360
- </widget>
361
- </item>
362
- <item row="1" column="0" colspan="2">
363
- <widget class="Line" name="line">
364
- <property name="orientation">
365
- <enum>Qt::Horizontal</enum>
366
- </property>
367
- </widget>
368
- </item>
369
- </layout>
370
- </item>
371
- <item row="2" column="1">
372
- <spacer name="verticalSpacer_2">
373
- <property name="orientation">
374
- <enum>Qt::Vertical</enum>
375
- </property>
376
- <property name="sizeType">
377
- <enum>QSizePolicy::Fixed</enum>
378
- </property>
379
- <property name="sizeHint" stdset="0">
380
- <size>
381
- <width>20</width>
382
- <height>20</height>
383
- </size>
384
- </property>
385
- </spacer>
386
- </item>
387
- <item row="1" column="2">
388
- <spacer name="horizontalSpacer">
389
- <property name="orientation">
390
- <enum>Qt::Horizontal</enum>
391
- </property>
392
- <property name="sizeType">
393
- <enum>QSizePolicy::Fixed</enum>
394
- </property>
395
- <property name="sizeHint" stdset="0">
396
- <size>
397
- <width>20</width>
398
- <height>20</height>
399
- </size>
400
- </property>
401
- </spacer>
402
- </item>
403
- <item row="1" column="0">
404
- <spacer name="horizontalSpacer_2">
405
- <property name="orientation">
406
- <enum>Qt::Horizontal</enum>
407
- </property>
408
- <property name="sizeType">
409
- <enum>QSizePolicy::Fixed</enum>
410
- </property>
411
- <property name="sizeHint" stdset="0">
412
- <size>
413
- <width>20</width>
414
- <height>20</height>
415
- </size>
416
- </property>
417
- </spacer>
418
- </item>
419
- </layout>
420
- </widget>
421
- <widget class="QStatusBar" name="statusbar"/>
422
- </widget>
423
- <resources/>
424
- <connections/>
425
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/results.ui DELETED
@@ -1,584 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>1246</width>
10
- <height>536</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <widget class="QWidget" name="centralwidget">
22
- <layout class="QGridLayout" name="gridLayout_2">
23
- <item row="4" column="1">
24
- <spacer name="verticalSpacer">
25
- <property name="orientation">
26
- <enum>Qt::Vertical</enum>
27
- </property>
28
- <property name="sizeType">
29
- <enum>QSizePolicy::Fixed</enum>
30
- </property>
31
- <property name="sizeHint" stdset="0">
32
- <size>
33
- <width>20</width>
34
- <height>20</height>
35
- </size>
36
- </property>
37
- </spacer>
38
- </item>
39
- <item row="3" column="1">
40
- <layout class="QGridLayout" name="gridLayout">
41
- <item row="1" column="0">
42
- <widget class="QGroupBox" name="guide_analysis">
43
- <property name="title">
44
- <string>Guide Analysis</string>
45
- </property>
46
- <layout class="QGridLayout" name="gridLayout_5">
47
- <item row="1" column="1">
48
- <widget class="QPushButton" name="cotargeting_button">
49
- <property name="sizePolicy">
50
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
51
- <horstretch>0</horstretch>
52
- <verstretch>0</verstretch>
53
- </sizepolicy>
54
- </property>
55
- <property name="minimumSize">
56
- <size>
57
- <width>125</width>
58
- <height>0</height>
59
- </size>
60
- </property>
61
- <property name="toolTip">
62
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Determine guides with synergistic PAMs (Ex. saCas9 and spCas9 compatible guides). &lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt; to analyze an organism for co-targeting guides, separate CSPR files must be generated for each additional endonuclease. Co-targeting endonucleases must have the same PAM directionality, same total gRNA length, and overlapping PAM sequences to be compatible.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
63
- </property>
64
- <property name="text">
65
- <string>Co-Targeting</string>
66
- </property>
67
- </widget>
68
- </item>
69
- <item row="0" column="0" colspan="2">
70
- <spacer name="verticalSpacer_5">
71
- <property name="orientation">
72
- <enum>Qt::Vertical</enum>
73
- </property>
74
- <property name="sizeType">
75
- <enum>QSizePolicy::Preferred</enum>
76
- </property>
77
- <property name="sizeHint" stdset="0">
78
- <size>
79
- <width>20</width>
80
- <height>10</height>
81
- </size>
82
- </property>
83
- </spacer>
84
- </item>
85
- <item row="1" column="0">
86
- <widget class="QPushButton" name="off_target_button">
87
- <property name="sizePolicy">
88
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
89
- <horstretch>0</horstretch>
90
- <verstretch>0</verstretch>
91
- </sizepolicy>
92
- </property>
93
- <property name="minimumSize">
94
- <size>
95
- <width>125</width>
96
- <height>0</height>
97
- </size>
98
- </property>
99
- <property name="toolTip">
100
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Perform off-target analysis on the selected guides.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
101
- </property>
102
- <property name="text">
103
- <string>Off-Target</string>
104
- </property>
105
- </widget>
106
- </item>
107
- <item row="2" column="0" colspan="2">
108
- <spacer name="verticalSpacer_6">
109
- <property name="orientation">
110
- <enum>Qt::Vertical</enum>
111
- </property>
112
- <property name="sizeType">
113
- <enum>QSizePolicy::Preferred</enum>
114
- </property>
115
- <property name="sizeHint" stdset="0">
116
- <size>
117
- <width>20</width>
118
- <height>10</height>
119
- </size>
120
- </property>
121
- </spacer>
122
- </item>
123
- </layout>
124
- </widget>
125
- </item>
126
- <item row="2" column="0" alignment="Qt::AlignLeft">
127
- <widget class="QPushButton" name="back_button">
128
- <property name="sizePolicy">
129
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
130
- <horstretch>0</horstretch>
131
- <verstretch>0</verstretch>
132
- </sizepolicy>
133
- </property>
134
- <property name="minimumSize">
135
- <size>
136
- <width>125</width>
137
- <height>0</height>
138
- </size>
139
- </property>
140
- <property name="text">
141
- <string>Back</string>
142
- </property>
143
- </widget>
144
- </item>
145
- <item row="2" column="1" alignment="Qt::AlignRight">
146
- <widget class="QPushButton" name="export_button">
147
- <property name="sizePolicy">
148
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
149
- <horstretch>0</horstretch>
150
- <verstretch>0</verstretch>
151
- </sizepolicy>
152
- </property>
153
- <property name="minimumSize">
154
- <size>
155
- <width>175</width>
156
- <height>0</height>
157
- </size>
158
- </property>
159
- <property name="toolTip">
160
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Export selected guides to a CSV file.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
161
- </property>
162
- <property name="text">
163
- <string>Export Selected gRNAs</string>
164
- </property>
165
- </widget>
166
- </item>
167
- <item row="0" column="0">
168
- <widget class="QGroupBox" name="guide_viewer">
169
- <property name="sizePolicy">
170
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
171
- <horstretch>0</horstretch>
172
- <verstretch>0</verstretch>
173
- </sizepolicy>
174
- </property>
175
- <property name="minimumSize">
176
- <size>
177
- <width>625</width>
178
- <height>0</height>
179
- </size>
180
- </property>
181
- <property name="title">
182
- <string>Guide Viewer</string>
183
- </property>
184
- <layout class="QGridLayout" name="gridLayout_4">
185
- <item row="5" column="0">
186
- <widget class="QLabel" name="geneLabel">
187
- <property name="sizePolicy">
188
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
189
- <horstretch>0</horstretch>
190
- <verstretch>0</verstretch>
191
- </sizepolicy>
192
- </property>
193
- <property name="text">
194
- <string>Gene:</string>
195
- </property>
196
- </widget>
197
- </item>
198
- <item row="10" column="0" colspan="5">
199
- <widget class="QTableWidget" name="targetTable"/>
200
- </item>
201
- <item row="9" column="0">
202
- <widget class="QCheckBox" name="checkBoxSelectAll">
203
- <property name="sizePolicy">
204
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
205
- <horstretch>0</horstretch>
206
- <verstretch>0</verstretch>
207
- </sizepolicy>
208
- </property>
209
- <property name="text">
210
- <string>Select All</string>
211
- </property>
212
- </widget>
213
- </item>
214
- <item row="9" column="1" alignment="Qt::AlignLeft">
215
- <widget class="QPushButton" name="filter_options_button">
216
- <property name="sizePolicy">
217
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
218
- <horstretch>0</horstretch>
219
- <verstretch>0</verstretch>
220
- </sizepolicy>
221
- </property>
222
- <property name="minimumSize">
223
- <size>
224
- <width>125</width>
225
- <height>0</height>
226
- </size>
227
- </property>
228
- <property name="toolTip">
229
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Additional options for filtering the Guide Viewer Table.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
230
- </property>
231
- <property name="text">
232
- <string>Filter Options</string>
233
- </property>
234
- </widget>
235
- </item>
236
- <item row="6" column="0">
237
- <widget class="QLabel" name="endoLabel">
238
- <property name="sizePolicy">
239
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
240
- <horstretch>0</horstretch>
241
- <verstretch>0</verstretch>
242
- </sizepolicy>
243
- </property>
244
- <property name="text">
245
- <string>Endonuclease:</string>
246
- </property>
247
- </widget>
248
- </item>
249
- <item row="11" column="0" colspan="2">
250
- <spacer name="verticalSpacer_7">
251
- <property name="orientation">
252
- <enum>Qt::Vertical</enum>
253
- </property>
254
- <property name="sizeType">
255
- <enum>QSizePolicy::Preferred</enum>
256
- </property>
257
- <property name="sizeHint" stdset="0">
258
- <size>
259
- <width>20</width>
260
- <height>10</height>
261
- </size>
262
- </property>
263
- </spacer>
264
- </item>
265
- <item row="0" column="0" colspan="2">
266
- <spacer name="verticalSpacer_3">
267
- <property name="orientation">
268
- <enum>Qt::Vertical</enum>
269
- </property>
270
- <property name="sizeType">
271
- <enum>QSizePolicy::Preferred</enum>
272
- </property>
273
- <property name="sizeHint" stdset="0">
274
- <size>
275
- <width>20</width>
276
- <height>10</height>
277
- </size>
278
- </property>
279
- </spacer>
280
- </item>
281
- <item row="9" column="2">
282
- <widget class="QPushButton" name="scoring_options_button">
283
- <property name="text">
284
- <string>Scoring Options</string>
285
- </property>
286
- </widget>
287
- </item>
288
- <item row="6" column="1" colspan="4">
289
- <layout class="QHBoxLayout" name="horizontalLayout_2">
290
- <item>
291
- <widget class="QComboBox" name="endonucleaseBox">
292
- <property name="sizePolicy">
293
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
294
- <horstretch>0</horstretch>
295
- <verstretch>0</verstretch>
296
- </sizepolicy>
297
- </property>
298
- <property name="minimumSize">
299
- <size>
300
- <width>225</width>
301
- <height>0</height>
302
- </size>
303
- </property>
304
- </widget>
305
- </item>
306
- </layout>
307
- </item>
308
- <item row="5" column="1" colspan="4">
309
- <layout class="QHBoxLayout" name="horizontalLayout">
310
- <item>
311
- <widget class="QComboBox" name="comboBoxGene">
312
- <property name="sizePolicy">
313
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
314
- <horstretch>0</horstretch>
315
- <verstretch>0</verstretch>
316
- </sizepolicy>
317
- </property>
318
- <property name="minimumSize">
319
- <size>
320
- <width>225</width>
321
- <height>0</height>
322
- </size>
323
- </property>
324
- </widget>
325
- </item>
326
- </layout>
327
- </item>
328
- </layout>
329
- </widget>
330
- </item>
331
- <item row="0" column="1" rowspan="2">
332
- <widget class="QGroupBox" name="gene_viewer">
333
- <property name="sizePolicy">
334
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
335
- <horstretch>0</horstretch>
336
- <verstretch>0</verstretch>
337
- </sizepolicy>
338
- </property>
339
- <property name="minimumSize">
340
- <size>
341
- <width>0</width>
342
- <height>0</height>
343
- </size>
344
- </property>
345
- <property name="title">
346
- <string>Gene Viewer</string>
347
- </property>
348
- <layout class="QGridLayout" name="gridLayout_6">
349
- <item row="3" column="1">
350
- <widget class="QLineEdit" name="lineEditStart">
351
- <property name="sizePolicy">
352
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
353
- <horstretch>0</horstretch>
354
- <verstretch>0</verstretch>
355
- </sizepolicy>
356
- </property>
357
- </widget>
358
- </item>
359
- <item row="3" column="2">
360
- <widget class="QLabel" name="endLabel">
361
- <property name="sizePolicy">
362
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
363
- <horstretch>0</horstretch>
364
- <verstretch>0</verstretch>
365
- </sizepolicy>
366
- </property>
367
- <property name="text">
368
- <string>Stop</string>
369
- </property>
370
- </widget>
371
- </item>
372
- <item row="3" column="0">
373
- <widget class="QLabel" name="startlabel">
374
- <property name="sizePolicy">
375
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
376
- <horstretch>0</horstretch>
377
- <verstretch>0</verstretch>
378
- </sizepolicy>
379
- </property>
380
- <property name="text">
381
- <string>Start</string>
382
- </property>
383
- </widget>
384
- </item>
385
- <item row="1" column="1">
386
- <widget class="QPushButton" name="highlight_gene_viewer_button">
387
- <property name="sizePolicy">
388
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
389
- <horstretch>0</horstretch>
390
- <verstretch>0</verstretch>
391
- </sizepolicy>
392
- </property>
393
- <property name="minimumSize">
394
- <size>
395
- <width>0</width>
396
- <height>0</height>
397
- </size>
398
- </property>
399
- <property name="toolTip">
400
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This button will highlight the sequences in the Gene Viewer that match the sequences selected in the table.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
401
- </property>
402
- <property name="text">
403
- <string>Highlight Guides</string>
404
- </property>
405
- </widget>
406
- </item>
407
- <item row="1" column="3">
408
- <widget class="QPushButton" name="clear_highlighted_guides_button">
409
- <property name="sizePolicy">
410
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
411
- <horstretch>0</horstretch>
412
- <verstretch>0</verstretch>
413
- </sizepolicy>
414
- </property>
415
- <property name="minimumSize">
416
- <size>
417
- <width>0</width>
418
- <height>0</height>
419
- </size>
420
- </property>
421
- <property name="toolTip">
422
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;This button clears all highlighted guides from the gene viewer box.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
423
- </property>
424
- <property name="text">
425
- <string>Clear Guides</string>
426
- </property>
427
- </widget>
428
- </item>
429
- <item row="3" column="3">
430
- <widget class="QLineEdit" name="lineEditEnd">
431
- <property name="sizePolicy">
432
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
433
- <horstretch>0</horstretch>
434
- <verstretch>0</verstretch>
435
- </sizepolicy>
436
- </property>
437
- </widget>
438
- </item>
439
- <item row="5" column="0" colspan="5">
440
- <widget class="QTextEdit" name="geneViewer">
441
- <property name="sizePolicy">
442
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
443
- <horstretch>0</horstretch>
444
- <verstretch>0</verstretch>
445
- </sizepolicy>
446
- </property>
447
- </widget>
448
- </item>
449
- <item row="0" column="0" colspan="5">
450
- <spacer name="verticalSpacer_4">
451
- <property name="orientation">
452
- <enum>Qt::Vertical</enum>
453
- </property>
454
- <property name="sizeType">
455
- <enum>QSizePolicy::Preferred</enum>
456
- </property>
457
- <property name="sizeHint" stdset="0">
458
- <size>
459
- <width>20</width>
460
- <height>10</height>
461
- </size>
462
- </property>
463
- </spacer>
464
- </item>
465
- <item row="1" column="4">
466
- <widget class="QCheckBox" name="displayGeneViewer">
467
- <property name="text">
468
- <string>Display On</string>
469
- </property>
470
- </widget>
471
- </item>
472
- <item row="7" column="0" colspan="5">
473
- <spacer name="verticalSpacer_8">
474
- <property name="orientation">
475
- <enum>Qt::Vertical</enum>
476
- </property>
477
- <property name="sizeType">
478
- <enum>QSizePolicy::Preferred</enum>
479
- </property>
480
- <property name="sizeHint" stdset="0">
481
- <size>
482
- <width>20</width>
483
- <height>10</height>
484
- </size>
485
- </property>
486
- </spacer>
487
- </item>
488
- <item row="3" column="4">
489
- <widget class="QPushButton" name="change_start_end_button">
490
- <property name="minimumSize">
491
- <size>
492
- <width>0</width>
493
- <height>0</height>
494
- </size>
495
- </property>
496
- <property name="toolTip">
497
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This button changes the start and end location of the Gene Viewer sequence, based on what is entered in the Start and Stop boxes.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
498
- </property>
499
- <property name="text">
500
- <string>Change Location</string>
501
- </property>
502
- </widget>
503
- </item>
504
- <item row="6" column="4">
505
- <widget class="QPushButton" name="reset_location_button">
506
- <property name="text">
507
- <string>Reset Location</string>
508
- </property>
509
- </widget>
510
- </item>
511
- </layout>
512
- </widget>
513
- </item>
514
- </layout>
515
- </item>
516
- <item row="3" column="0">
517
- <spacer name="horizontalSpacer">
518
- <property name="orientation">
519
- <enum>Qt::Horizontal</enum>
520
- </property>
521
- <property name="sizeType">
522
- <enum>QSizePolicy::Fixed</enum>
523
- </property>
524
- <property name="sizeHint" stdset="0">
525
- <size>
526
- <width>20</width>
527
- <height>20</height>
528
- </size>
529
- </property>
530
- </spacer>
531
- </item>
532
- <item row="0" column="1">
533
- <spacer name="verticalSpacer_2">
534
- <property name="orientation">
535
- <enum>Qt::Vertical</enum>
536
- </property>
537
- <property name="sizeType">
538
- <enum>QSizePolicy::Fixed</enum>
539
- </property>
540
- <property name="sizeHint" stdset="0">
541
- <size>
542
- <width>20</width>
543
- <height>20</height>
544
- </size>
545
- </property>
546
- </spacer>
547
- </item>
548
- <item row="1" column="1">
549
- <widget class="QLabel" name="title">
550
- <property name="text">
551
- <string>View Target</string>
552
- </property>
553
- </widget>
554
- </item>
555
- <item row="2" column="1">
556
- <widget class="Line" name="line">
557
- <property name="orientation">
558
- <enum>Qt::Horizontal</enum>
559
- </property>
560
- </widget>
561
- </item>
562
- <item row="3" column="2">
563
- <spacer name="horizontalSpacer_2">
564
- <property name="orientation">
565
- <enum>Qt::Horizontal</enum>
566
- </property>
567
- <property name="sizeType">
568
- <enum>QSizePolicy::Fixed</enum>
569
- </property>
570
- <property name="sizeHint" stdset="0">
571
- <size>
572
- <width>20</width>
573
- <height>20</height>
574
- </size>
575
- </property>
576
- </spacer>
577
- </item>
578
- </layout>
579
- </widget>
580
- <widget class="QStatusBar" name="statusbar"/>
581
- </widget>
582
- <resources/>
583
- <connections/>
584
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/scoring_window.ui DELETED
@@ -1,179 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>544</width>
10
- <height>249</height>
11
- </rect>
12
- </property>
13
- <property name="windowTitle">
14
- <string>MainWindow</string>
15
- </property>
16
- <widget class="QWidget" name="centralwidget">
17
- <layout class="QGridLayout" name="gridLayout">
18
- <item row="1" column="2">
19
- <spacer name="horizontalSpacer_2">
20
- <property name="orientation">
21
- <enum>Qt::Horizontal</enum>
22
- </property>
23
- <property name="sizeType">
24
- <enum>QSizePolicy::Fixed</enum>
25
- </property>
26
- <property name="sizeHint" stdset="0">
27
- <size>
28
- <width>5</width>
29
- <height>20</height>
30
- </size>
31
- </property>
32
- </spacer>
33
- </item>
34
- <item row="2" column="1">
35
- <spacer name="verticalSpacer">
36
- <property name="orientation">
37
- <enum>Qt::Vertical</enum>
38
- </property>
39
- <property name="sizeType">
40
- <enum>QSizePolicy::Fixed</enum>
41
- </property>
42
- <property name="sizeHint" stdset="0">
43
- <size>
44
- <width>20</width>
45
- <height>5</height>
46
- </size>
47
- </property>
48
- </spacer>
49
- </item>
50
- <item row="1" column="0">
51
- <spacer name="horizontalSpacer">
52
- <property name="orientation">
53
- <enum>Qt::Horizontal</enum>
54
- </property>
55
- <property name="sizeType">
56
- <enum>QSizePolicy::Fixed</enum>
57
- </property>
58
- <property name="sizeHint" stdset="0">
59
- <size>
60
- <width>5</width>
61
- <height>20</height>
62
- </size>
63
- </property>
64
- </spacer>
65
- </item>
66
- <item row="1" column="1">
67
- <widget class="QGroupBox" name="groupBox">
68
- <property name="sizePolicy">
69
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
70
- <horstretch>0</horstretch>
71
- <verstretch>0</verstretch>
72
- </sizepolicy>
73
- </property>
74
- <property name="title">
75
- <string>Select Scoring Algorithm</string>
76
- </property>
77
- <layout class="QGridLayout" name="gridLayout_2">
78
- <item row="0" column="0" colspan="4">
79
- <widget class="QLabel" name="label">
80
- <property name="sizePolicy">
81
- <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
82
- <horstretch>0</horstretch>
83
- <verstretch>0</verstretch>
84
- </sizepolicy>
85
- </property>
86
- <property name="toolTip">
87
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;CASPER needs to find an algorithm-specific amount of padding around each gRNA in order to score them. Please provide the same FASTA/FNA file that was used to make the CSPR DB.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
88
- </property>
89
- <property name="text">
90
- <string>Select FASTA file that was used to generate CSPR DBs:</string>
91
- </property>
92
- </widget>
93
- </item>
94
- <item row="1" column="3">
95
- <widget class="QPushButton" name="browse_button">
96
- <property name="text">
97
- <string>Browse...</string>
98
- </property>
99
- </widget>
100
- </item>
101
- <item row="2" column="0">
102
- <widget class="QLabel" name="label_2">
103
- <property name="text">
104
- <string>Select Algorithm:</string>
105
- </property>
106
- </widget>
107
- </item>
108
- <item row="1" column="0">
109
- <widget class="QLabel" name="fasta_label">
110
- <property name="sizePolicy">
111
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
112
- <horstretch>0</horstretch>
113
- <verstretch>0</verstretch>
114
- </sizepolicy>
115
- </property>
116
- <property name="toolTip">
117
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;CASPER needs to find an algorithm-specific amount of padding around each gRNA in order to score them. Please provide the same FASTA/FNA file that was used to make the CSPR DB.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
118
- </property>
119
- <property name="text">
120
- <string>Input FASTA:</string>
121
- </property>
122
- </widget>
123
- </item>
124
- <item row="2" column="1">
125
- <widget class="QRadioButton" name="azimuth_button">
126
- <property name="text">
127
- <string>Azimuth 2.0</string>
128
- </property>
129
- <property name="checked">
130
- <bool>true</bool>
131
- </property>
132
- </widget>
133
- </item>
134
- <item row="4" column="0" colspan="3">
135
- <widget class="QProgressBar" name="progressBar">
136
- <property name="value">
137
- <number>0</number>
138
- </property>
139
- </widget>
140
- </item>
141
- <item row="4" column="3">
142
- <widget class="QPushButton" name="submit_button">
143
- <property name="text">
144
- <string>Submit</string>
145
- </property>
146
- </widget>
147
- </item>
148
- <item row="1" column="1" colspan="2">
149
- <widget class="QLineEdit" name="fasta_edit">
150
- <property name="readOnly">
151
- <bool>true</bool>
152
- </property>
153
- </widget>
154
- </item>
155
- </layout>
156
- </widget>
157
- </item>
158
- <item row="0" column="1">
159
- <spacer name="verticalSpacer_3">
160
- <property name="orientation">
161
- <enum>Qt::Vertical</enum>
162
- </property>
163
- <property name="sizeType">
164
- <enum>QSizePolicy::Fixed</enum>
165
- </property>
166
- <property name="sizeHint" stdset="0">
167
- <size>
168
- <width>20</width>
169
- <height>5</height>
170
- </size>
171
- </property>
172
- </spacer>
173
- </item>
174
- </layout>
175
- </widget>
176
- </widget>
177
- <resources/>
178
- <connections/>
179
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/startupCASPER.ui DELETED
@@ -1,276 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <ui version="4.0">
3
- <class>MainWindow</class>
4
- <widget class="QMainWindow" name="MainWindow">
5
- <property name="geometry">
6
- <rect>
7
- <x>0</x>
8
- <y>0</y>
9
- <width>507</width>
10
- <height>205</height>
11
- </rect>
12
- </property>
13
- <property name="font">
14
- <font>
15
- <pointsize>12</pointsize>
16
- </font>
17
- </property>
18
- <property name="windowTitle">
19
- <string>MainWindow</string>
20
- </property>
21
- <property name="animated">
22
- <bool>true</bool>
23
- </property>
24
- <widget class="QWidget" name="centralwidget">
25
- <layout class="QGridLayout" name="gridLayout_2">
26
- <item row="2" column="1">
27
- <spacer name="verticalSpacer">
28
- <property name="orientation">
29
- <enum>Qt::Vertical</enum>
30
- </property>
31
- <property name="sizeType">
32
- <enum>QSizePolicy::Fixed</enum>
33
- </property>
34
- <property name="sizeHint" stdset="0">
35
- <size>
36
- <width>20</width>
37
- <height>20</height>
38
- </size>
39
- </property>
40
- </spacer>
41
- </item>
42
- <item row="0" column="1">
43
- <spacer name="verticalSpacer_2">
44
- <property name="orientation">
45
- <enum>Qt::Vertical</enum>
46
- </property>
47
- <property name="sizeType">
48
- <enum>QSizePolicy::Fixed</enum>
49
- </property>
50
- <property name="sizeHint" stdset="0">
51
- <size>
52
- <width>20</width>
53
- <height>20</height>
54
- </size>
55
- </property>
56
- </spacer>
57
- </item>
58
- <item row="1" column="1">
59
- <layout class="QGridLayout" name="gridLayout">
60
- <item row="2" column="0">
61
- <layout class="QVBoxLayout" name="verticalLayout">
62
- <item>
63
- <layout class="QHBoxLayout" name="horizontalLayout_2">
64
- <item>
65
- <widget class="QPushButton" name="goToMain">
66
- <property name="sizePolicy">
67
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
68
- <horstretch>0</horstretch>
69
- <verstretch>0</verstretch>
70
- </sizepolicy>
71
- </property>
72
- <property name="minimumSize">
73
- <size>
74
- <width>0</width>
75
- <height>0</height>
76
- </size>
77
- </property>
78
- <property name="maximumSize">
79
- <size>
80
- <width>16777215</width>
81
- <height>16777215</height>
82
- </size>
83
- </property>
84
- <property name="font">
85
- <font>
86
- <family>Arial</family>
87
- <pointsize>14</pointsize>
88
- </font>
89
- </property>
90
- <property name="text">
91
- <string>Main Program</string>
92
- </property>
93
- </widget>
94
- </item>
95
- <item>
96
- <widget class="QPushButton" name="goToNewGenome">
97
- <property name="sizePolicy">
98
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
99
- <horstretch>0</horstretch>
100
- <verstretch>0</verstretch>
101
- </sizepolicy>
102
- </property>
103
- <property name="minimumSize">
104
- <size>
105
- <width>0</width>
106
- <height>0</height>
107
- </size>
108
- </property>
109
- <property name="maximumSize">
110
- <size>
111
- <width>16777215</width>
112
- <height>16777215</height>
113
- </size>
114
- </property>
115
- <property name="font">
116
- <font>
117
- <family>Arial</family>
118
- <pointsize>14</pointsize>
119
- </font>
120
- </property>
121
- <property name="text">
122
- <string>New Genome</string>
123
- </property>
124
- </widget>
125
- </item>
126
- </layout>
127
- </item>
128
- </layout>
129
- </item>
130
- <item row="1" column="0">
131
- <layout class="QVBoxLayout" name="verticalLayout_3">
132
- <item>
133
- <layout class="QHBoxLayout" name="horizontalLayout">
134
- <item>
135
- <widget class="QLabel" name="label_2">
136
- <property name="sizePolicy">
137
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
138
- <horstretch>0</horstretch>
139
- <verstretch>0</verstretch>
140
- </sizepolicy>
141
- </property>
142
- <property name="maximumSize">
143
- <size>
144
- <width>16777215</width>
145
- <height>16777215</height>
146
- </size>
147
- </property>
148
- <property name="font">
149
- <font>
150
- <family>Arial</family>
151
- <pointsize>14</pointsize>
152
- </font>
153
- </property>
154
- <property name="text">
155
- <string>CASPER Database Directory:</string>
156
- </property>
157
- </widget>
158
- </item>
159
- <item>
160
- <widget class="QLineEdit" name="currentDirText">
161
- <property name="sizePolicy">
162
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
163
- <horstretch>0</horstretch>
164
- <verstretch>0</verstretch>
165
- </sizepolicy>
166
- </property>
167
- <property name="minimumSize">
168
- <size>
169
- <width>0</width>
170
- <height>0</height>
171
- </size>
172
- </property>
173
- <property name="maximumSize">
174
- <size>
175
- <width>16777215</width>
176
- <height>16777215</height>
177
- </size>
178
- </property>
179
- <property name="font">
180
- <font>
181
- <family>Arial</family>
182
- <pointsize>14</pointsize>
183
- </font>
184
- </property>
185
- </widget>
186
- </item>
187
- <item>
188
- <widget class="QPushButton" name="changeDir">
189
- <property name="sizePolicy">
190
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
191
- <horstretch>0</horstretch>
192
- <verstretch>0</verstretch>
193
- </sizepolicy>
194
- </property>
195
- <property name="minimumSize">
196
- <size>
197
- <width>0</width>
198
- <height>0</height>
199
- </size>
200
- </property>
201
- <property name="maximumSize">
202
- <size>
203
- <width>16777215</width>
204
- <height>16777215</height>
205
- </size>
206
- </property>
207
- <property name="font">
208
- <font>
209
- <family>Arial</family>
210
- <pointsize>14</pointsize>
211
- </font>
212
- </property>
213
- <property name="text">
214
- <string>Change...</string>
215
- </property>
216
- </widget>
217
- </item>
218
- </layout>
219
- </item>
220
- </layout>
221
- </item>
222
- <item row="0" column="0">
223
- <layout class="QVBoxLayout" name="verticalLayout_4">
224
- <item>
225
- <widget class="QLabel" name="logo">
226
- <property name="text">
227
- <string/>
228
- </property>
229
- <property name="scaledContents">
230
- <bool>true</bool>
231
- </property>
232
- </widget>
233
- </item>
234
- </layout>
235
- </item>
236
- </layout>
237
- </item>
238
- <item row="1" column="2">
239
- <spacer name="horizontalSpacer">
240
- <property name="orientation">
241
- <enum>Qt::Horizontal</enum>
242
- </property>
243
- <property name="sizeType">
244
- <enum>QSizePolicy::Fixed</enum>
245
- </property>
246
- <property name="sizeHint" stdset="0">
247
- <size>
248
- <width>20</width>
249
- <height>20</height>
250
- </size>
251
- </property>
252
- </spacer>
253
- </item>
254
- <item row="1" column="0">
255
- <spacer name="horizontalSpacer_2">
256
- <property name="orientation">
257
- <enum>Qt::Horizontal</enum>
258
- </property>
259
- <property name="sizeType">
260
- <enum>QSizePolicy::Fixed</enum>
261
- </property>
262
- <property name="sizeHint" stdset="0">
263
- <size>
264
- <width>20</width>
265
- <height>20</height>
266
- </size>
267
- </property>
268
- </spacer>
269
- </item>
270
- </layout>
271
- </widget>
272
- <widget class="QStatusBar" name="statusbar"/>
273
- </widget>
274
- <resources/>
275
- <connections/>
276
- </ui>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
utils/Algorithms.py DELETED
@@ -1,160 +0,0 @@
1
- """Algorithms.py File. This file contains the following classes: SeqTranslate.
2
- SeqTranslate Class. Used for interpreting base64 representations of the target locations as well as their sequences.
3
- To interpret these run the class instance at the bottom of the file with the desired base64 representation into the
4
- decompress_tuple function."""
5
- from PyQt5 import QtWidgets, Qt, uic, QtCore, QtGui
6
- import models.GlobalSettings as GlobalSettings
7
-
8
- # Takes a QtTableWidget and returns a list of headers
9
- def get_table_headers(table):
10
- labels = []
11
- for c in range(table.columnCount()):
12
- it = table.horizontalHeaderItem(c)
13
- labels.append(str(c+1) if it is None else it.text())
14
- return labels
15
-
16
- class SeqTranslate:
17
-
18
- def __init__(self):
19
- # Modification of MIME base64 coding so that +- can be used for strand direction
20
- self.base_array_64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=/"
21
-
22
- self.endo_info = dict()
23
- self.endo_import()
24
-
25
-
26
- # used to convert numbers in base4 back to nucleotides
27
- def int2nt(self, num):
28
- if num == 0:
29
- return 'A'
30
- elif num == 1:
31
- return 'T'
32
- elif num == 2:
33
- return 'C'
34
- elif num == 3:
35
- return 'G'
36
- else:
37
- return 'N'
38
-
39
- def nt2int(self,nt):
40
- if nt == 'A':
41
- return 0
42
- elif nt == 'T':
43
- return 1
44
- elif nt == 'C':
45
- return 2
46
- elif nt == 'G':
47
- return 3
48
- else:
49
- return 0
50
-
51
- def compress(self, uncompressed, base):
52
- compseq = 0
53
- if type(uncompressed) == str:
54
- for i in range(len(uncompressed)):
55
- val = self.nt2int(uncompressed[i]) * pow(4, i) # multiplying by power-4 converts to base10
56
- compseq += val
57
- uncompressed = compseq
58
- compreturn = str()
59
- while uncompressed >= base:
60
- rem = uncompressed%base
61
- uncompressed = int(uncompressed/base)
62
- compreturn = self.base_array_64[rem] + compreturn
63
- compreturn = self.base_array_64[uncompressed] + compreturn
64
- return compreturn
65
-
66
- def to_generic_compressed(self, seqobj):
67
- # Passed as a tuple from the repeats section of the .cspr file
68
- if type(seqobj) == list:
69
- gencomp = seqobj[0] + "." + seqobj[1][1:]
70
- else:
71
- split = seqobj.find("+")
72
- if split != -1:
73
- gencomp = seqobj[:split] + "." + seqobj[split+1:]
74
- else:
75
- split = seqobj.find("-")
76
- gencomp = seqobj[:split] + "." + seqobj[split+1:]
77
- return gencomp
78
-
79
- # Decompresses the base64 representation into base10. If toseq is true it returns the sequence itself (nucleotides)
80
- def decompress64(self, base64seq, slength=0, toseq=False):
81
- base10seq = int()
82
- if isinstance(base64seq, str):
83
- for i in range(len(base64seq)):
84
- power = len(base64seq) - (i+1)
85
- index = self.base_array_64.find(base64seq[i])
86
- if index != -1:
87
- base10seq += index*pow(64, power)
88
- else:
89
- base10seq = base64seq
90
- if toseq:
91
- seq = str()
92
- number = base10seq
93
- while number >= 4:
94
- rem = number % 4
95
- number = int(number/4)
96
- seq += self.int2nt(rem)
97
- seq += self.int2nt(number)
98
- for i in range(len(seq), slength):
99
- seq += 'A'
100
- return seq
101
- else:
102
- return base10seq
103
-
104
- def decompress_csf_tuple(self, locseq, bool=False, endo="spCas9"):
105
- # Lookup endonuclease sequence lengths for parsing
106
- if(bool == False):
107
- mytuple = locseq[:-1].split(",")
108
- else:
109
- mytuple = locseq.split(",")
110
- front_seq = mytuple[3]
111
-
112
- loc = self.decompress64(mytuple[0])
113
- seq = mytuple[1]
114
- scr = self.decompress64(mytuple[2])
115
- strand = seq.find("+")
116
- if strand != -1:
117
- dira = "+"
118
- sequence = seq[:strand]
119
- pam = seq[strand+1:]
120
- else:
121
- seq = seq.split("-")
122
- sequence = seq[0]
123
- pam = seq[1]
124
- dira = "-"
125
- if bool:
126
- seqlength = int(self.endo_info[endo][2]) - int(
127
- self.endo_info[endo][1]) # gets the tail sequence length for processing repeats
128
- else:
129
- seqlength = int(self.endo_info[endo][2]) # gets the total sequence length
130
- pamlength = len(self.endo_info[endo][0].split(",")[0]) # gets the length of the primary PAM
131
- #print(seqlength,pamlength)
132
- sequence = self.decompress64(sequence, seqlength, True)
133
- pam = self.decompress64(pam, pamlength, True)
134
- # The for loops fixes the problem of A's not being added to the end because they are removed on compression
135
- if(bool == True):
136
- sequence = sequence + front_seq
137
- return int(loc), str(sequence), pam, int(scr), dira, endo
138
-
139
- def endo_import(self):
140
- f = open(GlobalSettings.appdir + "CASPERinfo")
141
- while True:
142
- line = f.readline()
143
- if line.startswith("ENDONUCLEASES"):
144
- break
145
- while True:
146
- line = f.readline()
147
- if line.startswith("-"):
148
- break
149
- else:
150
- myinfo = line.split(";")
151
- self.endo_info[myinfo[0]] = myinfo[1:] # first is PAM list, second is seed length, third is tot length
152
-
153
-
154
-
155
-
156
- #S = SeqTranslate()
157
- #print(S.decompress_csf_tuple("Dx,|S62qFEz+Qy,k", endo='asCas12'))
158
- #print(S.decompress64("C86",False))
159
- #print(S.compress(440159,64))
160
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
utils/ui.py DELETED
@@ -1,113 +0,0 @@
1
- from PyQt5 import QtWidgets, QtGui, QtCore
2
- import traceback
3
- import math
4
- import models.GlobalSettings as GlobalSettings
5
-
6
- logger = GlobalSettings.logger
7
-
8
- def show_message(fontSize, icon, title, message, button=QtWidgets.QMessageBox.StandardButton.Close):
9
- try:
10
- msgBox = QtWidgets.QMessageBox()
11
- msgBox.setStyleSheet(f"font: {fontSize}pt 'Arial'")
12
- msgBox.setIcon(icon)
13
- msgBox.setWindowTitle(title)
14
- msgBox.setText(message)
15
- msgBox.addButton(button)
16
- msgBox.exec()
17
- except Exception as e:
18
- print(e)
19
-
20
- def show_error(message, e):
21
- try:
22
- logger.critical(message)
23
- logger.critical(e)
24
- logger.critical(traceback.format_exc())
25
-
26
- show_message(
27
- fontSize=12,
28
- icon=QtWidgets.QMessageBox.Icon.Critical,
29
- title="Fatal Error",
30
- message=f"Fatal Error:\n{str(e)}\n\nFor more information on this error, look at CASPER.log in the application folder."
31
- )
32
- except Exception as e:
33
- print(e)
34
-
35
- exit(-1)
36
-
37
- def scale_ui(window, base_width=1920, base_height=1080, font_size=12, header_font_size=30, custom_scale_width=None, custom_scale_height=None):
38
- try:
39
- window.repaint()
40
- QtWidgets.QApplication.processEvents()
41
-
42
- screen = window.screen()
43
- width = screen.geometry().width()
44
- height = screen.geometry().height()
45
-
46
- # Font scaling
47
- window.centralWidget().setStyleSheet(f"font: {font_size}pt 'Arial';")
48
- if hasattr(window, 'menuBar'):
49
- window.menuBar().setStyleSheet(f"font: {font_size}pt 'Arial';")
50
-
51
- # Header scaling
52
- # if hasattr(window, 'label_8'):
53
- # window.label_8.setStyleSheet(f"font: bold {header_font_size}pt 'Arial';")
54
-
55
- if hasattr(window, 'title'):
56
- scaled_title_font_size = int(header_font_size * (width / base_width))
57
- window.title.setStyleSheet(f"font: bold {scaled_title_font_size}pt 'Arial';")
58
-
59
- window.adjustSize()
60
-
61
- currentWidth = window.size().width()
62
- currentHeight = window.size().height()
63
-
64
- # Set logo if it's a StartupWindow
65
- if isinstance(window, QtWidgets.QMainWindow) and hasattr(window, 'logo'):
66
- window.logo.setPixmap(QtGui.QPixmap(GlobalSettings.appdir + "assets/CASPER-logo.jpg"))
67
-
68
- # Window resize and center
69
- scaledWidth = int((width * (custom_scale_width if custom_scale_width else 1150)) / base_width)
70
- scaledHeight = int((height * (custom_scale_height if custom_scale_height else 650)) / base_height)
71
-
72
- if scaledHeight < currentHeight:
73
- scaledHeight = currentHeight
74
- if scaledWidth < currentWidth:
75
- scaledWidth = currentWidth
76
-
77
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
78
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
79
- x = centerPoint.x() - (math.ceil(scaledWidth / 2))
80
- y = centerPoint.y() - (math.ceil(scaledHeight / 2))
81
- window.setGeometry(x, y, scaledWidth, scaledHeight)
82
-
83
- window.repaint()
84
- QtWidgets.QApplication.processEvents()
85
-
86
- return
87
-
88
- except Exception as e:
89
- show_error(f"Error in scaleUI() in {type(window).__name__}.", e)
90
-
91
- def center_ui(window):
92
- try:
93
- window.repaint()
94
- QtWidgets.QApplication.processEvents()
95
-
96
- # Get the dimensions of the window
97
- width = window.width()
98
- height = window.height()
99
-
100
- # Get the screen number based on the cursor's current position
101
- screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
102
- centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
103
-
104
- # Calculate new x and y coordinates
105
- x = centerPoint.x() - (width // 2)
106
- y = centerPoint.y() - (height // 2)
107
-
108
- # Set the new geometry for the window
109
- window.setGeometry(x, y, width, height)
110
- window.repaint()
111
- except Exception as e:
112
- print(f"Error centering window: {e}")
113
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
utils/web.py DELETED
@@ -1,17 +0,0 @@
1
- import webbrowser
2
- from utils.ui import show_error
3
-
4
- def ncbi_blast_page():
5
- open_webpage("https://blast.ncbi.nlm.nih.gov/Blast.cgi")
6
-
7
- def ncbi_page():
8
- open_webpage("https://www.ncbi.nlm.nih.gov/")
9
-
10
- def repo_page():
11
- open_webpage("https://github.com/TrinhLab/CASPERapp")
12
-
13
- def open_webpage(url):
14
- try:
15
- webbrowser.open(url, new=2)
16
- except Exception as e:
17
- show_error("Error in open_webpage()", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/AnnotationParser.py DELETED
@@ -1,429 +0,0 @@
1
- ###############################################################################
2
- # INPUTS: inputs are the annotation files to parse. Currently, only gbff is supported.
3
- # OUTPUTS: the outputs are data structures that store the parsed data
4
- ################################################################################
5
-
6
- from PyQt5 import QtWidgets
7
- import gffutils
8
- import models.GlobalSettings as GlobalSettings
9
- import os
10
- from Bio import SeqIO
11
- import traceback
12
-
13
- logger = GlobalSettings.logger
14
-
15
- class Annotation_Parser:
16
- def __init__(self):
17
- try:
18
- #variables to use
19
- self.annotationFileName = "" #this is the variable that holds the filename itself
20
- self.txtLocusTag = False
21
- self.isGff = False
22
- self.isTxt = False
23
- self.max_chrom = 0
24
-
25
- #dictionary used for finding the genes in a txt annotation file
26
- #key: locus_tag
27
- #value: List of lists
28
- # essentially its all based on locus tag. So the key is the locus tag, and its data is:
29
- # [genomic accession, int, start, end, +\-]
30
- self.reg_dict = dict()
31
-
32
- #parallel dictionary used for the txt annotaion file
33
- #key: name + symbol (space in between each word)
34
- #value: locus_tag (indexes dict)
35
- self.para_dict = dict()
36
-
37
- #list of tuples containing (chromosome/scaffold # {int}, Feature matching search criteria {SeqFeature Object})
38
- self.results_list = list()
39
-
40
- except Exception as e:
41
- logger.critical("Error initializing Annotation_Parser class.")
42
- logger.critical(e)
43
- logger.critical(traceback.format_exc())
44
- msgBox = QtWidgets.QMessageBox()
45
- msgBox.setStyleSheet("font: " + str(GlobalSettings.mainWindow.fontSize) + "pt 'Arial'")
46
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
47
- msgBox.setWindowTitle("Fatal Error")
48
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
49
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
50
- msgBox.exec()
51
-
52
- exit(-1)
53
-
54
- ### This function takes a list of lists and flattens it into a single list. Useful when dealing with a list of lists where the nested lists only have 1 entry.
55
- def flatten_list(self,t):
56
- return [item.lower() for sublist in t for item in sublist]
57
-
58
- ### This function finds how many chromosomes are within the selcted annotation file and returns the value
59
- def get_max_chrom(self):
60
- parser = SeqIO.parse(self.annotationFileName, 'genbank') # Initialize parser (iterator) for each query
61
- for i, record in enumerate(parser):
62
- max_chrom = i+1
63
- return max_chrom
64
-
65
- def get_sequence_info(self, query):
66
- try:
67
- self.results_list.clear()
68
- parser = SeqIO.parse(self.annotationFileName, 'genbank') # Initialize parser (iterator) for each query
69
- for j,record in enumerate(parser): # Each record corresponds to a chromosome/scaffold in the FNA/FASTA file
70
- tmp = str(record.seq).find(query)
71
- if tmp != -1: # If match is found
72
- return (j+1,tmp+1,tmp+len(query)) # Chromosome number, start index, stop index
73
- else:
74
- tmp = str(record.seq.reverse_complement()).find(query) # Check the reverse complement now
75
- if tmp != -1: # If match is found
76
- return (j+1,tmp-len(query),tmp-1) # Chromosome number, start index, stop index
77
- else:
78
- continue
79
- return False
80
-
81
- except Exception as e:
82
- logger.critical("Error in get_sequence_info() in annotation parser.")
83
- logger.critical(e)
84
- logger.critical(traceback.format_exc())
85
- msgBox = QtWidgets.QMessageBox()
86
- msgBox.setStyleSheet("font: " + str(GlobalSettings.mainWindow.fontSize) + "pt 'Arial'")
87
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
88
- msgBox.setWindowTitle("Fatal Error")
89
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
90
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
91
- msgBox.exec()
92
-
93
- exit(-1)
94
-
95
- ### The workhorse function of AnnotationParser, this searches the annotation file for the user's search and returns features matching the description.
96
- def genbank_search(self, queries, same_search):
97
- index_number = 0
98
- try:
99
- if same_search: # If searching for the same thing, just return the results from last time
100
- return self.results_list
101
- else:
102
- self.results_list.clear()
103
- for i, query in enumerate(queries):
104
- parser = SeqIO.parse(self.annotationFileName, 'genbank') # Initialize parser (iterator) for each query
105
- for j,record in enumerate(parser): # Each record corresponds to a chromosome/scaffold in the FNA/FASTA file
106
- if i == 0:
107
- index_number += 1
108
- for feature in record.features: # Each feature corresponds to a gene, tRNA, rep_origin, etc. in the given record (chromosome/scaffold)
109
- if "translation" in feature.qualifiers:
110
- if query.lower() in " ".join(self.flatten_list(feature.qualifiers.values())[:-1]) and feature.type != "source" and feature.type != "gene": # If search matches the feature's qualifiers somewhere, save it
111
- self.results_list.append((j+1,feature))
112
- else: # If search not in the feature's qualifiers, move to the next feature
113
- continue
114
- else:
115
- if query.lower() in " ".join(self.flatten_list(feature.qualifiers.values())) and feature.type != "source" and feature.type != "gene": # If search matches the feature's qualifiers somewhere, save it
116
- self.results_list.append((j+1,feature))
117
- else: # If search not in the feature's qualifiers, move to the next feature
118
- continue
119
- self.max_chrom = index_number # Counts the number of chromosomes/scaffolds in the organism (only do this once, even if there are multiple queries)
120
- else:
121
- for feature in record.features:
122
- if "translation" in feature.qualifiers:
123
- if query.lower() in " ".join(self.flatten_list(feature.qualifiers.values())[:-1]) and feature.type != "source" and feature.type != "gene": # If search matches the feature's qualifiers somewhere, save it
124
- self.results_list.append((j+1,feature))
125
- else: # If search not in the feature's qualifiers, move to the next feature
126
- continue
127
- else:
128
- if query.lower() in " ".join(self.flatten_list(feature.qualifiers.values())) and feature.type != "source" and feature.type != "gene": # If search matches the feature's qualifiers somewhere, save it
129
- self.results_list.append((j+1,feature))
130
- else: # If search not in the feature's qualifiers, move to the next feature
131
- continue
132
- return self.results_list
133
-
134
- except Exception as e:
135
- logger.critical("Error in genbank_search() in annotation parser.")
136
- logger.critical(e)
137
- logger.critical(traceback.format_exc())
138
- msgBox = QtWidgets.QMessageBox()
139
- msgBox.setStyleSheet("font: " + str(GlobalSettings.mainWindow.fontSize) + "pt 'Arial'")
140
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
141
- msgBox.setWindowTitle("Fatal Error")
142
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
143
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
144
- msgBox.exec()
145
-
146
- exit(-1)
147
-
148
-
149
-
150
-
151
- # This function parses gff files and stores them in a dictionary
152
- # It also creates a parallel dictionary to use in searching
153
- # Precondition: ONLY TO BE USED WITH GFF FILES
154
- def gff_parse(self):
155
- try:
156
- self.reg_dict.clear()
157
- self.para_dict.clear()
158
- prevFirstIndex = ""
159
- indexNumber = 1
160
- fileStream = open(self.annotationFileName)
161
- data_base_file_name = GlobalSettings.CSPR_DB + "/" + "gff_database.db"
162
-
163
- # temp list will be the following each time it is put into the dictionary:
164
- # [Sequence ID (genomic accession or scaffold), the index number itself, the feature type (cds, gene, mrna), the start(-1), end, and the strand]
165
- tempList = list()
166
- currentLocusTag = ""
167
- para_dict_key_string = ""
168
-
169
- # initialize the data base (this is what parses it for me)
170
- print("Intializing the data base")
171
- db = gffutils.create_db(self.annotationFileName, dbfn=data_base_file_name, force=True, keep_order=True,
172
- merge_strategy='merge', sort_attribute_values=True)
173
- print("Finished intializing")
174
-
175
- # call the feature version of that data base now
176
- db = gffutils.FeatureDB(data_base_file_name, keep_order=True)
177
-
178
- # now we go through that data base and get the data we want
179
- for feature in db.all_features(limit=None, strand=None, featuretype=None, order_by=None, reverse=False,
180
- completely_within=False):
181
- # if the genomic accession/scaffold/chromseome changes, update the indexNumber
182
- if prevFirstIndex != feature.seqid and prevFirstIndex != "":
183
- indexNumber += 1
184
- # if we find a new gene, update the locus_tag/name
185
- if feature.featuretype == "gene" or feature.featuretype == 'pseudogene':
186
-
187
- # check and see if locus tag is in the attributes, go on the Name if locus_tag is not in there
188
- if 'locus_tag' in feature.attributes:
189
- currentLocusTag = feature.attributes['locus_tag'][0]
190
- else:
191
- currentLocusTag = feature.attributes["Name"][0]
192
-
193
- # once the locus tag changes, append it to the para_dict
194
- if para_dict_key_string != "":
195
- if para_dict_key_string not in self.para_dict:
196
- self.para_dict[para_dict_key_string] = list()
197
- self.para_dict[para_dict_key_string].append(currentLocusTag)
198
- else:
199
- if currentLocusTag not in self.para_dict[para_dict_key_string]:
200
- self.para_dict[para_dict_key_string].append(currentLocusTag)
201
- para_dict_key_string = ""
202
-
203
- tempList = [currentLocusTag, indexNumber, feature.featuretype, feature.start - 1, feature.end,
204
- feature.strand]
205
-
206
- # insert that locus tag/name into the dictionary
207
- if currentLocusTag not in self.reg_dict:
208
- self.reg_dict[currentLocusTag] = []
209
- self.reg_dict[currentLocusTag].append(tempList)
210
- elif currentLocusTag in self.reg_dict:
211
- self.reg_dict[currentLocusTag].append(tempList)
212
-
213
- # go through each of this child's children
214
- for child in db.children(feature.id, level=None, featuretype=None, order_by=None, reverse=False,
215
- limit=None, completely_within=False):
216
- tempList = [currentLocusTag, indexNumber, child.featuretype, child.start - 1, child.end, child.strand]
217
-
218
- # only insert it if it hasn't been inserted before
219
- if tempList not in self.reg_dict[currentLocusTag]:
220
- self.reg_dict[currentLocusTag].append(tempList)
221
-
222
- # now go through the other ones which are not region
223
- elif feature.featuretype != "region" and feature.featuretype != "telomere" and feature.featuretype != "origin_of_replication":
224
- tempList = [currentLocusTag, indexNumber, feature.featuretype, feature.start - 1, feature.end,
225
- feature.strand]
226
-
227
- # only insert if it hasn't been inserted before
228
- if tempList not in self.reg_dict[currentLocusTag]:
229
- self.reg_dict[currentLocusTag].append(tempList)
230
-
231
- # now same as above, go through the children again
232
- for child in db.children(feature.id, level=None, featuretype=None, order_by=None, reverse=False,
233
- limit=None, completely_within=False):
234
- tempList = [currentLocusTag, indexNumber, child.featuretype, child.start - 1, child.end,
235
- child.strand]
236
-
237
- if tempList not in self.reg_dict[currentLocusTag]:
238
- self.reg_dict[currentLocusTag].append(tempList)
239
-
240
- # now we need to get the para_dict up and running
241
- # get the stuff out of the product part
242
- if 'product' in feature.attributes and feature.featuretype == "CDS":
243
- if para_dict_key_string == "":
244
- para_dict_key_string = feature.attributes['product'][0]
245
- else:
246
- para_dict_key_string = para_dict_key_string + ";" + feature.attributes['product'][0]
247
- # get the stuff out of the Note part
248
- if 'Note' in feature.attributes:
249
- if para_dict_key_string == "":
250
- para_dict_key_string = feature.attributes['Note'][0]
251
- else:
252
- para_dict_key_string = para_dict_key_string + ";" + feature.attributes['Note'][0]
253
-
254
- prevFirstIndex = feature.seqid
255
- self.max_chrom = indexNumber
256
- except Exception as e:
257
- logger.critical("Error in gff_parse() in annotation parser.")
258
- logger.critical(e)
259
- logger.critical(traceback.format_exc())
260
- msgBox = QtWidgets.QMessageBox()
261
- msgBox.setStyleSheet("font: " + str(GlobalSettings.mainWindow.fontSize) + "pt 'Arial'")
262
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
263
- msgBox.setWindowTitle("Fatal Error")
264
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
265
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
266
- msgBox.exec()
267
-
268
- exit(-1)
269
-
270
- # This function parses txt files and stores them in a dictionary
271
- # It also creates a parallel dictionary to use in searching
272
- # Precondition: ONLY TO BE USED WITH TXT FILES
273
- def txt_parse(self):
274
- try:
275
- self.reg_dict.clear()
276
- prevGenAccession = ""
277
- indexNumber = 1
278
- fileStream = open(self.annotationFileName)
279
- buffer = ""
280
- currentLocusTag = ""
281
- para_dict_key_string = ""
282
-
283
- while(True): # this loop breaks out when buffer string is empty
284
- buffer = fileStream.readline()
285
-
286
- if(buffer.startswith("#")): #skip lines that start with #
287
- continue
288
- else:
289
- if(len(buffer) <= 2): # break out once we reach the end of the file
290
- break
291
-
292
- splitLine = buffer[:-1].split("\t")
293
-
294
- # increment indexNumber when genomic access changes
295
- if prevGenAccession != splitLine[6] and prevGenAccession != "":
296
- indexNumber += 1
297
-
298
- # if parsing on locus_tag, use the locus_tag as the key for the dict
299
- if self.txtLocusTag:
300
- currentLocusTag = splitLine[16]
301
- values = [currentLocusTag, indexNumber, splitLine[0], int(splitLine[7]) - 1, int(splitLine[8]), splitLine[9]]
302
-
303
- if currentLocusTag not in self.reg_dict:
304
- self.reg_dict[currentLocusTag] = [values]
305
- elif currentLocusTag in self.reg_dict:
306
- self.reg_dict[currentLocusTag].append(values)
307
-
308
- # if no locus_tag, parse on product_accession, use the product_accession as the key for the dict
309
- elif not self.txtLocusTag:
310
- currentLocusTag = splitLine[10]
311
- values = [currentLocusTag, indexNumber, splitLine[0], int(splitLine[7]) - 1, int(splitLine[8]), splitLine[9]]
312
-
313
- if currentLocusTag not in self.reg_dict:
314
- self.reg_dict[currentLocusTag] = [values]
315
- elif currentLocusTag in self.reg_dict:
316
- self.reg_dict[currentLocusTag].append(values)
317
-
318
- if splitLine[13] != '':
319
- if para_dict_key_string == '':
320
- para_dict_key_string = splitLine[13] + ';'
321
- else:
322
- para_dict_key_string = para_dict_key_string + splitLine[13] + ';'
323
-
324
- # leaving this in for now, it's related accession
325
- #if splitLine[12] != '':
326
- # if para_dict_key_string == '':
327
- # para_dict_key_string = splitLine[12] + ';'
328
- # else:
329
- # para_dict_key_string = para_dict_key_string + splitLine[12] + ';'
330
-
331
-
332
- if splitLine[14] != '':
333
- if para_dict_key_string == '':
334
- para_dict_key_string = splitLine[14] + ';'
335
- else:
336
- para_dict_key_string = para_dict_key_string + splitLine[14] + ';'
337
-
338
- para_dict_key_string = para_dict_key_string.replace(',', '')
339
- # set the parallel dictionary's key string
340
- #para_dict_key_string = splitLine[13] + ";" + splitLine[12] + ";" + splitLine[14]
341
-
342
- # if the current line we're on has the data we want for the parellel dictionary, store it
343
- if len(para_dict_key_string) > 3:
344
- if para_dict_key_string[len(para_dict_key_string) - 1] == ';':
345
- para_dict_key_string = para_dict_key_string[0:len(para_dict_key_string) - 1]
346
-
347
- if para_dict_key_string not in self.para_dict: # make a new input into the dict
348
- self.para_dict[para_dict_key_string] = [currentLocusTag]
349
- elif para_dict_key_string in self.para_dict:
350
- if currentLocusTag not in self.para_dict[para_dict_key_string]:
351
- # only append it to the dict's list if it isn't currently in there
352
- self.para_dict[para_dict_key_string].append(currentLocusTag)
353
-
354
- para_dict_key_string = ""
355
- prevGenAccession = splitLine[6]
356
- self.max_chrom = indexNumber
357
- except Exception as e:
358
- logger.critical("Error in txt_parse() in annotation parser.")
359
- logger.critical(e)
360
- logger.critical(traceback.format_exc())
361
- msgBox = QtWidgets.QMessageBox()
362
- msgBox.setStyleSheet("font: " + str(GlobalSettings.mainWindow.fontSize) + "pt 'Arial'")
363
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
364
- msgBox.setWindowTitle("Fatal Error")
365
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
366
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
367
- msgBox.exec()
368
-
369
- exit(-1)
370
-
371
- # This function checks to see which file we are parsing
372
- # It also checks whether to parse based on locus_tag or product accession (txt files only)
373
- # Then it calls the respective parser functions used
374
- def find_which_file_version(self):
375
- try:
376
- if self.annotationFileName == "" or GlobalSettings.mainWindow.annotation_files.currentText() == "None":
377
- return -1
378
- if "gff" in self.annotationFileName:
379
- ### gff file support currently deprecated
380
- """
381
- self.isGff = True
382
- self.gff_parse()
383
- """
384
- print("Error: Wrong annotation file format")
385
- return -1
386
-
387
- elif "feature_table" in self.annotationFileName:
388
- ### feature table file support currently deprecated
389
- # now that we know it's a txt file and not a gff, check and see if we will be parsing by locus tag or
390
- # product accession
391
- """
392
- fileStream = open(self.annotationFileName)
393
-
394
- #skip all of the lines that start with #
395
- buf = fileStream.readline()
396
- while buf.startswith("#"):
397
- buf = fileStream.readline()
398
-
399
- # split it and see if the locus tag spot has data in it
400
- split = buf.split("\t")
401
- if split[16] != "": # if it does, we are parsing based on locus_tag
402
- self.txtLocusTag = True
403
- elif split[16] == "": # if not, we are parsing based on product accession
404
- self.txtLocusTag = False
405
- fileStream.close()
406
- self.isTxt = True
407
- self.txt_parse()
408
- """
409
- print("Error: Wrong annotation file format")
410
- return -1
411
- elif "gbff" or "gbk" in self.annotationFileName:
412
- return "gbff"
413
- # return -1 to throw the error window in main
414
- else:
415
- return -1
416
- except Exception as e:
417
- logger.critical("Error in find_which_file_version() in annotation parser.")
418
- logger.critical(e)
419
- logger.critical(traceback.format_exc())
420
- msgBox = QtWidgets.QMessageBox()
421
- msgBox.setStyleSheet("font: " + str(GlobalSettings.mainWindow.fontSize) + "pt 'Arial'")
422
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
423
- msgBox.setWindowTitle("Fatal Error")
424
- msgBox.setText("Fatal Error:\n"+str(e)+ "\n\nFor more information on this error, look at CASPER.log in the application folder.")
425
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Close)
426
- msgBox.exec()
427
-
428
- exit(-1)
429
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/AnnotationWindow.py DELETED
@@ -1,125 +0,0 @@
1
- import models.GlobalSettings as GlobalSettings
2
- from utils.ui import show_error, scale_ui, center_ui
3
- from PyQt5 import QtWidgets, QtCore, uic, Qt
4
- from views.annotation_functions import *
5
- import traceback
6
-
7
- logger = GlobalSettings.logger
8
-
9
- class AnnotationWindow(QtWidgets.QMainWindow):
10
- def __init__(self, info_path):
11
- super(AnnotationWindow, self).__init__()
12
- uic.loadUi(GlobalSettings.appdir + 'ui/annotation_details.ui', self)
13
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
14
- self.Submit_button.clicked.connect(self.submit)
15
- self.Go_Back_Button.clicked.connect(self.go_Back)
16
- self.select_all_checkbox.stateChanged.connect(self.select_all_genes)
17
- self.fontSize = 12
18
- self.mainWindow = ""
19
- self.type = ""
20
- self.mwfg = self.frameGeometry() ##Center window
21
- self.cp = QtWidgets.QDesktopWidget().availableGeometry().center() ##Center window
22
- self.switcher_table = [1, 1, 1, 1, 1, 1, 1, 1]
23
- self.tableWidget.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
24
- self.tableWidget.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
25
- self.tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
26
- self.tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
27
- self.tableWidget.setAutoScroll(False)
28
- self.tableWidget.horizontalHeader().sectionClicked.connect(self.table_sorting)
29
-
30
- scale_ui(self, custom_scale_width=1150, custom_scale_height=650)
31
-
32
- def table_sorting(self, logicalIndex):
33
- try:
34
- self.switcher_table[logicalIndex] *= -1
35
- order = QtCore.Qt.DescendingOrder if self.switcher_table[logicalIndex] == -1 else QtCore.Qt.AscendingOrder
36
- self.tableWidget.sortItems(logicalIndex, order)
37
- except Exception as e:
38
- show_error("table_sorting() in Annotation Window", e)
39
-
40
- #submit selected rows for results to process
41
- def submit(self):
42
- try:
43
- self.mainWindow.collect_table_data_nonkegg()
44
- self.mainWindow.show() # Open main window back up
45
- except Exception as e:
46
- logger.critical("Error in submit() in AnnotationWindow.")
47
- logger.critical(e)
48
- logger.critical(traceback.format_exc())
49
- show_error("submit() in AnnotationWindow", e)
50
- finally:
51
- self.hide() # Close annotation window regardless of success or failure
52
-
53
- #go back to main
54
- def go_Back(self):
55
- try:
56
- self.tableWidget.clear()
57
- self.mainWindow.searches.clear()
58
- self.tableWidget.setColumnCount(0)
59
- self.mainWindow.show()
60
- self.mainWindow.progressBar.setValue(0)
61
- self.hide()
62
- except Exception as e:
63
- show_error("go_Back() in AnnotationWindow", e)
64
- self.mainWindow.checkBoxes.clear()
65
-
66
- # this is the connection for the select all checkbox - selects/deselects all the genes in the table
67
- # this function is very similar to the other fill_table, it just works with the other types of annotation files
68
- def fill_table_nonKegg(self, mainWindow, results_list):
69
- try:
70
- self.tableWidget.clearContents()
71
- self.mainWindow = mainWindow
72
- self.tableWidget.setColumnCount(5)
73
- self.mainWindow.progressBar.setValue(85)
74
- self.tableWidget.setHorizontalHeaderLabels(["Feature Type", "Chromosome/Scaffold #", "Feature ID/Locus Tag", "Feature Name", "Feature Description"])
75
-
76
- mainWindow.checkBoxes = []
77
- self.type = "nonkegg"
78
-
79
- for index, result in enumerate(results_list[:1000]): # Limit to first 1000 results
80
- self.tableWidget.setRowCount(index + 1) # Increment table row count
81
- chrom, feature = result
82
-
83
- # Create and set table items
84
- items = [
85
- QtWidgets.QTableWidgetItem(feature.type),
86
- QtWidgets.QTableWidgetItem(str(chrom)),
87
- QtWidgets.QTableWidgetItem(get_id(feature)),
88
- QtWidgets.QTableWidgetItem(get_name(feature)),
89
- QtWidgets.QTableWidgetItem(get_description(feature))
90
- ]
91
-
92
- for col, item in enumerate(items):
93
- self.tableWidget.setItem(index, col, item)
94
-
95
- mainWindow.checkBoxes.append((chrom, feature, index))
96
-
97
- self.tableWidget.resizeColumnsToContents()
98
- mainWindow.hide()
99
-
100
- #center on current screen
101
- center_ui(self)
102
- self.show()
103
- self.activateWindow()
104
-
105
- return 0
106
- except Exception as e:
107
- show_error("fill_table_nonKegg() in AnnotationWindow", e)
108
-
109
- # this is the connection for the select all checkbox - selects/deselects all the genes in the table
110
- def select_all_genes(self):
111
- try:
112
- if self.select_all_checkbox.isChecked():
113
- self.tableWidget.selectAll()
114
- else:
115
- self.tableWidget.clearSelection()
116
- except Exception as e:
117
- show_error("select_all_genes() in AnnotationWindow", e)
118
-
119
- # this function calls the closingWindow class.
120
- def closeEvent(self, event):
121
- try:
122
- GlobalSettings.mainWindow.closeFunction()
123
- except Exception as e:
124
- show_error("closeEvent() in AnnotationWindow", e)
125
- event.accept()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/CMainWindow.py DELETED
@@ -1,1000 +0,0 @@
1
- import platform
2
- import controllers.ncbi as ncbi
3
- import os
4
- from utils.Algorithms import get_table_headers
5
- from models.CSPRparser import CSPRparser
6
- import glob
7
- import traceback
8
- import models.GlobalSettings as GlobalSettings
9
- from PyQt5 import QtWidgets, QtGui, QtCore, uic, Qt
10
- from utils.ui import scale_ui, center_ui, show_message, show_error
11
- from views.annotation_functions import *
12
- from views.AnnotationParser import Annotation_Parser
13
- from views.AnnotationWindow import AnnotationWindow
14
- import views.genomeBrowser as genomeBrowser
15
- from views.NewGenome import NewGenome
16
- from views.NewEndonuclease import NewEndonuclease
17
- from controllers.CoTargeting import CoTargeting
18
- from views.generateLib import genLibrary
19
- import webbrowser
20
- from controllers.Results import Results
21
- from views.export_tool import export_tool
22
- from views.closingWin import closingWindow
23
- from utils.web import ncbi_page, repo_page, ncbi_blast_page
24
-
25
- logger = GlobalSettings.logger
26
-
27
- fontSize = 12
28
-
29
- class CMainWindow(QtWidgets.QMainWindow):
30
- def __init__(self, info_path):
31
- super(CMainWindow, self).__init__()
32
- uic.loadUi(GlobalSettings.appdir + 'ui/CASPER_main.ui', self)
33
- self.dbpath = ""
34
- self.inputstring = "" # This is the search string
35
- self.info_path = info_path
36
- self.anno_name = ""
37
- self.endo_name = ""
38
- self.fontSize = 12
39
- self.org = ""
40
- self.TNumbers = {} # the T numbers from a kegg search
41
- self.orgcodes = {} # Stores the Kegg organism code by the format {full name : organism code}
42
- self.gene_list = {} # list of genes (no ides what they pertain to
43
- self.searches = {}
44
- self.checkBoxes = []
45
- self.genlib_list = [] # This list stores selected SeqFeatures from annotation window
46
- self.checked_info = {}
47
- self.check_ntseq_info = {} # the ntsequences that go along with the checked_info
48
- self.annotation_parser = Annotation_Parser()
49
- self.link_list = list() # the list of the downloadable links from the NCBI search
50
- self.organismDict = dict() # the dictionary for the links to download. Key is the description of the organism, value is the ID that can be found in link_list
51
- self.results_list = list()
52
- self.organismData = list()
53
- self.ncbi = ncbi.NCBI_search_tool()
54
-
55
- groupbox_style = """
56
- QGroupBox:title{subcontrol-origin: margin;
57
- left: 10px;
58
- padding: 0 5px 0 5px;}
59
- QGroupBox#Step1{border: 2px solid rgb(111,181,110);
60
- border-radius: 9px;
61
- margin-top: 10px;
62
- font: bold 14pt 'Arial';}
63
- """
64
-
65
- self.Step1.setStyleSheet(groupbox_style)
66
- self.Step2.setStyleSheet(groupbox_style.replace("Step1", "Step2"))
67
- self.Step3.setStyleSheet(groupbox_style.replace("Step1", "Step3"))
68
- self.CASPER_Navigation.setStyleSheet(groupbox_style.replace("Step1", "CASPER_Navigation").replace("solid","dashed").replace("rgb(111,181,110)","rgb(88,89,91)"))
69
-
70
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
71
- self.pushButton_FindTargets.clicked.connect(self.gather_settings)
72
- self.pushButton_ViewTargets.clicked.connect(self.view_results)
73
- self.pushButton_ViewTargets.setEnabled(False)
74
- self.GenerateLibrary.setEnabled(False)
75
- self.radioButton_Gene.clicked.connect(self.toggle_annotation)
76
- self.radioButton_Position.clicked.connect(self.toggle_annotation)
77
-
78
- """ Connect functions to buttons """
79
- self.newGenome_button.clicked.connect(self.launch_newGenome) # Connect launch function to New Genome
80
- self.newEndo_button.clicked.connect(self.launch_newEndonuclease) # Connect launch function to New Endonuclease
81
- self.multitargeting_button.clicked.connect(self.changeto_multitargeting) # Connect launch function to Multitargeting
82
- self.populationAnalysis_button.clicked.connect(self.changeto_population_Analysis) # Connect launch function to PA
83
- self.GenerateLibrary.clicked.connect(self.prep_genlib)
84
-
85
- """ Connect functions to actions (menu bar) """
86
- self.actionOpen_Genome_Browser.triggered.connect(self.launch_newGenomeBrowser)
87
- self.actionExit.triggered.connect(self.close_app)
88
- self.visit_repo.triggered.connect(repo_page)
89
- self.actionChange_Directory.triggered.connect(self.change_directory)
90
- self.actionNCBI.triggered.connect(ncbi_page)
91
- # self.actionCasper2.triggered.connect(self.open_casper2_web_page)
92
- self.actionNCBI_BLAST.triggered.connect(ncbi_blast_page)
93
-
94
-
95
-
96
- self.progressBar.setMinimum(0)
97
- self.progressBar.setMaximum(100)
98
- self.progressBar.reset()
99
- self.Annotation_Window = AnnotationWindow(info_path)
100
- self.geneEntryField.setPlaceholderText("Example Inputs: \n\n"
101
- "Option 1: Feature (ID, Locus Tag, or Name)\n"
102
- "Example: 854068/YOL086C/ADH1 for S. cerevisiae alcohol dehydrogenase 1\n\n"
103
- "Option 2: Position (chromosome,start,stop)\n"
104
- "Example: 1,1,1000 for targeting chromosome 1, base pairs 1 to 1000\n\n"
105
- "Option 3: Sequence (must be within the selected organism)\n"
106
- "Example: Any nucleotide sequence between 100 and 10,000 base pairs.\n\n"
107
- "*Note: to multiplex, separate multiple queries by new lines*\n"
108
- "Example:\n"
109
- "1,1,1000\n"
110
- "5,1,500\n"
111
- "etc.")
112
-
113
- # show functionalities on window
114
- self.newGenome = NewGenome(info_path)
115
- self.newEndonuclease = NewEndonuclease()
116
- self.CoTargeting = CoTargeting(info_path)
117
- self.Results = Results()
118
- self.export_tool_window = export_tool()
119
- self.genLib = genLibrary()
120
- self.myClosingWindow = closingWindow()
121
- self.genomebrowser = genomeBrowser.genomebrowser()
122
- self.launch_ncbi_button.clicked.connect(self.launch_ncbi)
123
-
124
- self.first_show = True
125
- scale_ui(self, custom_scale_width=1150, custom_scale_height=650)
126
-
127
- # this function prepares everything for the generate library function
128
- # it is very similar to the gather settings, how ever it stores the data instead of calling the Annotation Window class
129
- # it moves the data onto the generateLib function, and then opens that window
130
- def prep_genlib(self):
131
- # make sure the user actually inputs something
132
- try:
133
- inputstring = str(self.geneEntryField.toPlainText())
134
- if (inputstring.startswith("Example Inputs:") or inputstring == ""):
135
- msgBox = QtWidgets.QMessageBox()
136
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
137
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
138
- msgBox.setWindowTitle("Error")
139
- msgBox.setText("No gene has been entered. Please enter a gene.")
140
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
141
- msgBox.exec()
142
-
143
- else:
144
- # standardize the input
145
- inputstring = inputstring.lower()
146
- found_matches_bool = True
147
- # call the respective function
148
- self.progressBar.setValue(10)
149
- if self.radioButton_Gene.isChecked():
150
- if len(self.genlib_list) > 0:
151
- found_matches_bool = True
152
- else:
153
- found_matches_bool = False
154
- elif self.radioButton_Position.isChecked() or self.radioButton_Sequence.isChecked():
155
- msgBox = QtWidgets.QMessageBox()
156
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
157
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
158
- msgBox.setWindowTitle("Error")
159
- msgBox.setText("Generate Library can only work with feature searches.")
160
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
161
- msgBox.exec()
162
-
163
- return
164
- """
165
- elif self.radioButton_Position.isChecked():
166
- pinput = inputstring.split(';')
167
- found_matches_bool = self.run_results("position", pinput,openAnnoWindow=False)
168
- elif self.radioButton_Sequence.isChecked():
169
- sinput = inputstring
170
- found_matches_bool = self.run_results("sequence", sinput, openAnnoWindow=False)
171
- """
172
- # if matches are found
173
- if found_matches_bool == True:
174
- # get the cspr file name
175
- cspr_file = self.organisms_to_files[self.orgChoice.currentText()][self.endoChoice.currentText()][0]
176
- if platform.system() == 'Windows':
177
- cspr_file = GlobalSettings.CSPR_DB + '\\' + cspr_file
178
- else:
179
- cspr_file = GlobalSettings.CSPR_DB + '/' + cspr_file
180
- kegg_non = 'non_kegg'
181
-
182
- # launch generateLib
183
- self.progressBar.setValue(100)
184
-
185
- # calculate the total number of matches found
186
- tempSum = len(self.genlib_list)
187
-
188
- # warn the user if the number is greater than 50
189
- if tempSum > 50:
190
- msgBox = QtWidgets.QMessageBox()
191
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
192
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
193
- msgBox.setWindowTitle("Many Matches Found")
194
- msgBox.setText("More than 50 matches have been found. Continuing could cause a slow down...\n\n Do you wish to continue?")
195
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
196
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
197
- msgBox.exec()
198
-
199
- if (msgBox.result() == QtWidgets.QMessageBox.No):
200
- self.searches.clear()
201
- self.progressBar.setValue(0)
202
- return -2
203
-
204
- self.genLib.launch(self.genlib_list,cspr_file, kegg_non)
205
- else:
206
- self.progressBar.setValue(0)
207
- except Exception as e:
208
- show_error("Error in prep_genlib() in main", e)
209
-
210
- # Function for collecting the settings from the input field and transferring them to run_results
211
- def gather_settings(self):
212
- try:
213
- ### If user searches multiple times for the same thing, this avoids re-searching the entire annotation file
214
- check_org = self.orgChoice.currentText().lower()
215
- check_endo = self.endoChoice.currentText().lower()
216
- check_anno_name = self.annotation_files.currentText().lower()
217
- check_input = str(self.geneEntryField.toPlainText()).lower()
218
- if (check_input == self.inputstring and check_org == self.org and check_anno_name == self.anno_name and check_endo == self.endo_name):
219
- same_search = True
220
- else:
221
- self.org = check_org
222
- self.anno_name = check_anno_name
223
- self.inputstring = check_input
224
- self.endo_name = check_endo
225
- same_search = False
226
-
227
- # Error check: make sure the user actually inputs something
228
- if (self.inputstring.startswith("Example Inputs:") or self.inputstring == ""):
229
- msgBox = QtWidgets.QMessageBox()
230
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
231
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
232
- msgBox.setWindowTitle("Error")
233
- msgBox.setText(
234
- "No feature has been searched for. Please enter a search.")
235
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
236
- msgBox.exec()
237
-
238
- else:
239
-
240
- ### Remove additional scoring columns if necessary
241
- header = get_table_headers(self.Results.targetTable) # Returns headers of the target table in View Targets window
242
- col_indices = [header.index(x) for x in GlobalSettings.algorithms if x in header] # Returns the index(es) of the alternative scoring column(s) in the target table of View Targets window
243
- if len(col_indices) > 0: # If alternative scoring has been done
244
- for i in col_indices:
245
- self.Results.targetTable.removeColumn(i)
246
- self.Results.targetTable.resizeColumnsToContents()
247
-
248
- self.progressBar.setValue(10)
249
- if self.radioButton_Gene.isChecked():
250
- ginput = [x.strip() for x in self.inputstring.split('\n')] # Split search based on newline character and remove deadspace
251
- self.run_results("feature", ginput, same_search)
252
- elif self.radioButton_Position.isChecked():
253
- pinput = [x.strip() for x in self.inputstring.split('\n')] # Split search based on newline character and remove deadspace
254
- self.run_results("position", pinput, same_search)
255
- elif self.radioButton_Sequence.isChecked():
256
- sinput = self.inputstring
257
- self.run_results("sequence", sinput, same_search)
258
- except Exception as e:
259
- show_error("Error in gather_settings() in main", e)
260
-
261
- # ---- Following functions are for running the auxillary algorithms and windows ---- #
262
- # this function is parses the annotation file given, and then goes through and goes onto results
263
- # it will call other versions of collect_table_data and fill_table that work with these file types
264
- # this function should work with the any type of annotation file, besides kegg.
265
- # this assumes that the parsers all store the data the same way, which gff and feature table do
266
- # please make sure the genbank parser stores the data in the same way
267
- # so far the gff files seems to all be different. Need to think about how we want to parse it
268
- def run_results_own_ncbi_file(self, inputstring, fileName, same_search, openAnnoWindow=True):
269
- try:
270
- self.set_progress(35)
271
- self.results_list = self.annotation_parser.genbank_search(inputstring, same_search)
272
-
273
- cspr_file = self.organisms_to_files[self.orgChoice.currentText()][self.endoChoice.currentText()][0]
274
- cspr_file = os.path.join(GlobalSettings.CSPR_DB, cspr_file)
275
-
276
- own_cspr_parser = CSPRparser(cspr_file)
277
- own_cspr_parser.read_first_lines()
278
- if len(own_cspr_parser.karystatsList) != self.annotation_parser.max_chrom:
279
- show_message(
280
- fontSize=12,
281
- icon=QtWidgets.QMessageBox.Icon.Warning,
282
- title="Warning:",
283
- message="The number of chromosomes do not match. This could cause errors.",
284
- button=QtWidgets.QMessageBox.StandardButton.Ok
285
- )
286
- self.set_progress(60)
287
-
288
- self.searches.clear()
289
-
290
- self.set_progress(75)
291
- if not self.results_list:
292
- show_message(
293
- fontSize=12,
294
- icon=QtWidgets.QMessageBox.Icon.Critical,
295
- title="No Matches Found",
296
- message="No matches found with that search, please try again.",
297
- button=QtWidgets.QMessageBox.StandardButton.Ok
298
- )
299
- self.set_progress(0)
300
- return False if not openAnnoWindow else None
301
-
302
- self.set_progress(80)
303
-
304
- return self.Annotation_Window.fill_table_nonKegg(self, self.results_list) if openAnnoWindow else True
305
- except Exception as e:
306
- show_error(f"Error in run_results_own_ncbi_file() in main.", e)
307
-
308
- def set_progress(self, value):
309
- self.progressBar.setValue(value)
310
-
311
- def run_results(self, inputtype, inputstring, same_search, openAnnoWindow=True):
312
- try:
313
- file_name = self.annotation_files.currentText()
314
- for file in glob.glob(GlobalSettings.CSPR_DB + "/**/*.gb*", recursive=True):
315
- if file_name in file:
316
- self.annotation_parser.annotationFileName = file
317
- break
318
- self.Results.annotation_path = self.annotation_parser.annotationFileName
319
-
320
- progvalue = 15
321
- self.searches = {}
322
- self.gene_list = {}
323
- self.progressBar.setValue(progvalue)
324
-
325
- try:
326
- self.Results.endonucleaseBox.currentIndexChanged.disconnect()
327
- except Exception as e:
328
- pass
329
- # set Results endo combo box
330
- self.Results.endonucleaseBox.clear()
331
-
332
- # set the results window endoChoice box menu
333
- # set the mainWindow's endoChoice first, and then loop through and set the rest of them
334
- self.Results.endonucleaseBox.addItem(self.endoChoice.currentText())
335
- for item in self.organisms_to_endos[str(self.orgChoice.currentText())]:
336
- if item != self.Results.endonucleaseBox.currentText():
337
- self.Results.endonucleaseBox.addItem(item)
338
-
339
- self.Results.endonucleaseBox.currentIndexChanged.connect(self.Results.changeEndonuclease)
340
- self.Results.get_endo_data()
341
-
342
- # self.Results.change_start_end_button.setEnabled(False)
343
- self.Results.displayGeneViewer.setChecked(0)
344
-
345
- if inputtype == "feature":
346
-
347
- fileType = self.annotation_parser.find_which_file_version()
348
-
349
- # if the parser retuns the 'wrong file type' error
350
- if fileType == -1:
351
- msgBox = QtWidgets.QMessageBox()
352
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
353
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
354
- msgBox.setWindowTitle("Error:")
355
- msgBox.setText("Feature search requires a GenBank formatted annotation file. Please select a file from the dropdown menu or search by position")
356
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
357
- msgBox.exec()
358
-
359
- self.progressBar.setValue(0)
360
- return
361
-
362
- # make sure an annotation file has been selected
363
- if self.annotation_files.currentText() == "None":
364
- msgBox = QtWidgets.QMessageBox()
365
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
366
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
367
- msgBox.setWindowTitle("No Annotation")
368
- msgBox.setText("Search by feature requires a GenBank annotation file. Please select one from the dropdown menu or search by position.")
369
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
370
- msgBox.exec()
371
-
372
- self.progressBar.setValue(0)
373
- return
374
- # this now just goes onto the other version of run_results
375
- myBool = self.run_results_own_ncbi_file(inputstring, self.annotation_files.currentText(), same_search, openAnnoWindow=openAnnoWindow)
376
- if not openAnnoWindow:
377
- return myBool
378
- else:
379
- self.progressBar.setValue(0)
380
- return
381
-
382
- # position code below
383
- if inputtype == "position":
384
- full_org = str(self.orgChoice.currentText())
385
- self.checked_info.clear()
386
- self.check_ntseq_info.clear()
387
-
388
- for item in inputstring: # Loop through each search
389
- searchIndices = [x.strip() for x in item.split(',')] # Parse input query
390
- ### Make sure the right amount of arguments were passed
391
- if len(searchIndices) != 3:
392
- msgBox = QtWidgets.QMessageBox()
393
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
394
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
395
- msgBox.setWindowTitle("Position Error: Invalid Input")
396
- msgBox.setText(
397
- "There are 3 arguments required for this function: chromosome, start position, and end position.")
398
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
399
- msgBox.exec()
400
-
401
- self.progressBar.setValue(0)
402
- return
403
-
404
- ### Make sure user inputs digits
405
- if not searchIndices[0].isdigit() or not searchIndices[1].isdigit() or not searchIndices[2].isdigit():
406
- msgBox = QtWidgets.QMessageBox()
407
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
408
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
409
- msgBox.setWindowTitle("Position Error: Invalid Input")
410
- msgBox.setText(
411
- "The positions given must be integers. Please try again.")
412
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
413
- msgBox.exec()
414
-
415
- self.progressBar.setValue(0)
416
- return
417
-
418
- ### Make sure start is less than end
419
- elif int(searchIndices[1]) >= int(searchIndices[2]):
420
- msgBox = QtWidgets.QMessageBox()
421
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
422
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
423
- msgBox.setWindowTitle("Position Error: Start Must Be Less Than End")
424
- msgBox.setText(
425
- "The start index must be less than the end index.")
426
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
427
- msgBox.exec()
428
-
429
- self.progressBar.setValue(0)
430
- return
431
-
432
- ### Make sure range isn't too large
433
- elif abs(int(searchIndices[2])-int(searchIndices[1])) > 50000:
434
- msgBox = QtWidgets.QMessageBox()
435
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
436
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
437
- msgBox.setWindowTitle("Position Error: Range Too Large")
438
- msgBox.setText(
439
- "The search range must be less than 50,000 nt.")
440
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
441
- msgBox.exec()
442
-
443
- self.progressBar.setValue(0)
444
- return
445
-
446
- ### Make sure chromosome exists
447
- elif int(searchIndices[0]) > self.annotation_parser.get_max_chrom():
448
- msgBox = QtWidgets.QMessageBox()
449
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
450
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
451
- msgBox.setWindowTitle("Position Error: Chromsome Doesn't Exist")
452
- msgBox.setText(
453
- "Chromosome %s does not exist in the selected annotation file." % searchIndices[0])
454
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
455
- msgBox.exec()
456
-
457
- self.progressBar.setValue(0)
458
- return
459
-
460
- # append the data into the checked_info
461
- tempString = 'chrom: ' + str(searchIndices[0]) + ',start: ' + str(searchIndices[1]) + ',end: ' + str(searchIndices[2])
462
- self.checked_info[tempString] = (int(searchIndices[0]), int(searchIndices[1])-1, int(searchIndices[2]))
463
-
464
- self.progressBar.setValue(50)
465
- self.Results.transfer_data(full_org, self.organisms_to_files[full_org], [str(self.endoChoice.currentText())], os.getcwd(), self.checked_info, self.check_ntseq_info,inputtype)
466
- self.Results.load_gene_viewer()
467
- self.progressBar.setValue(100)
468
- self.pushButton_ViewTargets.setEnabled(True)
469
- self.GenerateLibrary.setEnabled(True)
470
-
471
- # sequence code below
472
- if inputtype == "sequence":
473
- fileType = self.annotation_parser.find_which_file_version()
474
- # if the parser retuns the 'wrong file type' error
475
- if fileType == -1:
476
- msgBox = QtWidgets.QMessageBox()
477
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
478
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
479
- msgBox.setWindowTitle("Error:")
480
- msgBox.setText("Search by sequence requires a GenBank annotation file. Please select one from the dropdown menu or search by position.")
481
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
482
- msgBox.exec()
483
-
484
- self.progressBar.setValue(0)
485
- return
486
- if self.annotation_files.currentText() == "None":
487
- msgBox = QtWidgets.QMessageBox()
488
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
489
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
490
- msgBox.setWindowTitle("Error:")
491
- msgBox.setText("Search by sequence requires a GenBank annotation file. Please select one from the dropdown menu or search by position.")
492
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
493
- msgBox.exec()
494
-
495
- self.progressBar.setValue(0)
496
- return
497
-
498
-
499
- checkString = 'AGTCN'
500
- full_org = str(self.orgChoice.currentText())
501
- self.checked_info.clear()
502
- self.progressBar.setValue(10)
503
- inputstring = inputstring.replace('\n','').upper().strip()
504
-
505
- # make sure all the chars are one of A, G, T, C, or N
506
- for letter in inputstring:
507
- if letter not in checkString:
508
- msgBox = QtWidgets.QMessageBox()
509
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
510
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
511
- msgBox.setWindowTitle("Sequence Error")
512
- msgBox.setText(
513
- "The sequence must consist of A, G, T, C, or N. No other characters are allowed.")
514
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
515
- msgBox.exec()
516
-
517
- self.progressBar.setValue(0)
518
- return
519
-
520
- # check to make sure that the use gave a long enough sequence
521
- if len(inputstring) < 100:
522
- msgBox = QtWidgets.QMessageBox()
523
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
524
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
525
- msgBox.setWindowTitle("Error")
526
- msgBox.setText(
527
- "The sequence given is too small. At least 100 characters are required.")
528
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
529
- msgBox.exec()
530
-
531
- self.progressBar.setValue(0)
532
- return
533
-
534
- # give a warning if the length of the sequence is long
535
- if len(inputstring) > 10000:
536
- msgBox = QtWidgets.QMessageBox()
537
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
538
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
539
- msgBox.setWindowTitle("Large Sequence Detected")
540
- msgBox.setText(
541
- "The sequence given is too large one.\n\nPlease input a sequence less than 10kb in length.")
542
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
543
- msgBox.exec()
544
-
545
- self.progressBar.setValue(0)
546
- return
547
-
548
- self.progressBar.setValue(30)
549
-
550
- # Check the GBFF file for the sequence
551
- my_check = self.annotation_parser.get_sequence_info(inputstring)
552
-
553
- self.progressBar.setValue(55) # Update progress bar
554
-
555
- if type(my_check) == bool: # This means the sequence was not found
556
- msgBox = QtWidgets.QMessageBox()
557
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
558
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
559
- msgBox.setWindowTitle("Sequence Not Found")
560
- msgBox.setText(
561
- "The sequence entered was not found.\n\nPlease input a sequence that is in the selected organism.")
562
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
563
- msgBox.exec()
564
- self.progressBar.setValue(0)
565
- return
566
-
567
- else: # This means the sequence was found
568
- # append the data into the checked_info
569
- tempString = 'chrom: ' + str(my_check[0]) + ',start: ' + str(my_check[1]) + ',end: ' + str(my_check[2])
570
- self.checked_info[tempString] = (int(my_check[0]), int(my_check[1])-1, int(my_check[2]))
571
-
572
- self.progressBar.setValue(75) # Update progress bar
573
-
574
- self.Results.transfer_data(full_org, self.organisms_to_files[full_org], [str(self.endoChoice.currentText())], os.getcwd(), self.checked_info, self.check_ntseq_info, inputtype)
575
- self.Results.load_gene_viewer()
576
- self.progressBar.setValue(100)
577
- self.pushButton_ViewTargets.setEnabled(True)
578
- self.GenerateLibrary.setEnabled(True)
579
-
580
-
581
- except Exception as e:
582
- show_error("Error in run_results() in main", e)
583
-
584
- def handle_feature_search(self, input_string, open_anno_window):
585
- file_type = self.annotation_parser.find_which_file_version()
586
- if file_type == -1 or self.annotation_files.currentText() == "None":
587
- self.show_error_message("Feature search requires a GenBank formatted annotation file.")
588
- return False
589
-
590
- return self.run_results_own_ncbi_file(input_string, self.annotation_files.currentText(), same_search, open_anno_window)
591
-
592
-
593
- def launch_newGenome(self):
594
- try:
595
- # Update endo list
596
- self.newGenome.fillEndo()
597
- if self.newGenome.first_show:
598
- center_ui(self.newGenome)
599
- self.newGenome.first_show = False
600
- self.hide()
601
- self.newGenome.show()
602
- except Exception as e:
603
- show_error("Error in launch_newGenome() in main", e)
604
-
605
- def launch_newEndonuclease(self):
606
- try:
607
- center_ui(self.newEndonuclease)
608
- self.newEndonuclease.show()
609
- self.newEndonuclease.activateWindow()
610
- except Exception as e:
611
- show_error("Error in launch_newEndonuclease() in main", e)
612
-
613
- #launch genome browser tool
614
- def launch_newGenomeBrowser(self):
615
- try:
616
- self.genomebrowser.createGraph(self)
617
- except Exception as e:
618
- show_error("Error in launch_newGenomeBrowser() in main", e)
619
-
620
- def launch_ncbi(self):
621
- try:
622
- msgBox = QtWidgets.QMessageBox()
623
- msgBox.setStyleSheet(f"font: {self.fontSize}pt 'Arial'")
624
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Information)
625
- msgBox.setWindowTitle("Note:")
626
- msgBox.setText(
627
- "NCBI Annotation Guidelines:\n\nDownload annotation files of the exact species and strain used in Analyze New Genome.\n\nMismatched annotation files will inhibit downstream analyses.")
628
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
629
- msgBox.exec()
630
-
631
- if self.ncbi.first_show:
632
- self.ncbi.first_show = False
633
- center_ui(self.ncbi)
634
-
635
- self.ncbi.show()
636
- self.ncbi.activateWindow()
637
- except Exception as e:
638
- show_error("launch_ncbi() in main", e)
639
-
640
- # this function does the same stuff that the other collect_table_data does, but works with the other types of files
641
- def collect_table_data_nonkegg(self):
642
- try:
643
- # start out the same as the other collect_table_data
644
- self.checked_info.clear()
645
- self.genlib_list.clear()
646
- self.check_ntseq_info.clear()
647
- full_org = str(self.orgChoice.currentText())
648
- holder = ()
649
- selected_indices = []
650
- selected_rows = self.Annotation_Window.tableWidget.selectionModel().selectedRows()
651
- for ind in sorted(selected_rows):
652
- selected_indices.append(ind.row())
653
-
654
- for item in self.checkBoxes:
655
- feature = item[1]
656
- # If inidices of checkBoxes list and selected rows in table match...
657
- if item[2] in selected_indices:
658
- holder = (item[0],int(feature.location.start),int(feature.location.end)) # Tuple order: Feature chromosome/scaffold number, feature start, feature end
659
- ### If locus tag available, combine with gene name to create dict key
660
- if 'locus_tag' in feature.qualifiers:
661
- tag = feature.qualifiers['locus_tag'][0]
662
- key = tag + ": " + get_name(feature)
663
- else:
664
- key = get_name(feature)
665
- self.checked_info[key] = holder
666
- self.genlib_list.append((item[0],feature)) # Tuple order: Feature chromosome/scaffold number, SeqFeature object
667
- else:
668
- # If item was not selected in the table, go to the next item
669
- continue
670
-
671
- # now call transfer data
672
- self.progressBar.setValue(95)
673
- self.Results.transfer_data(full_org, self.organisms_to_files[full_org], [str(self.endoChoice.currentText())], os.getcwd(),
674
- self.checked_info, self.check_ntseq_info,inputtype="feature")
675
- self.Results.load_gene_viewer()
676
-
677
- self.progressBar.setValue(100)
678
- self.pushButton_ViewTargets.setEnabled(True)
679
- self.GenerateLibrary.setEnabled(True)
680
- except Exception as e:
681
- show_error("Error in collect_table_data_nonkegg() in main", e)
682
-
683
- def separate_line(self, input_string):
684
- try:
685
- export_array = []
686
- while True:
687
- index = input_string.find('\n')
688
- if index == -1:
689
- if len(input_string) == 0:
690
- return export_array
691
- else:
692
- export_array.append(input_string)
693
- return export_array
694
- export_array.append(input_string[:index])
695
- input_string = input_string[index + 1:]
696
- except Exception as e:
697
- show_error("Error in seperate_line() in main", e)
698
-
699
- def removeWhiteSpace(self, strng):
700
- try:
701
- while True:
702
- if len(strng) == 0 or (strng[0] != " " and strng[0] != "\n"):
703
- break
704
- strng = strng[1:]
705
- while True:
706
- if len(strng) == 0 or (strng[len(strng) - 1] != " " and strng[0] != "\n"):
707
- return strng
708
- strng = strng[:len(strng) - 1]
709
- except Exception as e:
710
- show_error("Error in removeWhiteSpace() in main", e)
711
-
712
- # Function to enable and disable the Annotation function if searching by position or sequence
713
- def toggle_annotation(self):
714
- try:
715
- if self.radioButton_Gene.isChecked():
716
- self.Step2.setEnabled(True)
717
- else:
718
- self.Step2.setEnabled(True)
719
- except Exception as e:
720
- show_error("Error in toggle_annotation() in main", e)
721
-
722
- def fill_annotation_dropdown(self):
723
- try:
724
- #recursive search for all GenBank files in casper db folder
725
- self.annotation_files.clear()
726
- annotation_files = glob.glob(GlobalSettings.CSPR_DB + "/**/*.gb*", recursive=True)
727
- if platform.system() == "Windows":
728
- for i in range(len(annotation_files)):
729
- annotation_files[i] = annotation_files[i].replace("/","\\")
730
- annotation_files[i] = annotation_files[i][annotation_files[i].rfind("\\") + 1:]
731
- else:
732
- for i in range(len(annotation_files)):
733
- annotation_files[i] = annotation_files[i].replace("\\","/")
734
- annotation_files[i] = annotation_files[i][annotation_files[i].rfind("/") + 1:]
735
-
736
- annotation_files.sort(key=str.lower)
737
- self.annotation_files.addItems(annotation_files)
738
- self.annotation_files.addItems(["None"])
739
- except Exception as e:
740
- show_error("Error in fill_annotation_dropdown() in main", e)
741
-
742
- def make_dictonary(self):
743
- try:
744
- url = "https://www.genome.jp/dbget-bin/get_linkdb?-t+genes+gn:" + self.TNumbers[
745
- self.Annotations_Organism.currentText()]
746
- source_code = requests.get(url, verify=False)
747
- plain_text = source_code.text
748
- buf = io.StringIO(plain_text)
749
-
750
- while True:
751
- line = buf.readline()
752
- if line[0] == "-":
753
- break
754
- while True:
755
- line = buf.readline()
756
- if line[1] != "a":
757
- return
758
- line = line[line.find(">") + 1:]
759
- seq = line[line.find(":") + 1:line.find("<")]
760
- line = line[line.find(">") + 1:]
761
-
762
- i = 0
763
- while True:
764
- if line[i] == " ":
765
- i = i + 1
766
- else:
767
- break
768
- key = line[i:line.find("\n") - 1]
769
- if key in self.gene_list:
770
- if seq not in self.gene_list[key]:
771
- self.gene_list[key].append(seq)
772
- else:
773
- self.gene_list[key] = [seq]
774
- z = 5
775
- except Exception as e:
776
- show_error("Error in make_dictionary() in main", e)
777
-
778
- def organism_finder(self, long_str):
779
- try:
780
- semi = long_str.find(";")
781
- index = 1
782
- while True:
783
- if long_str[semi - index] == " ":
784
- break
785
- index = index + 1
786
- return long_str[:semi - index]
787
- except Exception as e:
788
- show_error("Error in organism_finder() in main", e)
789
-
790
- # This method is for testing the execution of a button call to make sure the button is linked properly
791
- def testexe(self):
792
- try:
793
- msgBox = QtWidgets.QMessageBox()
794
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
795
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
796
- msgBox.setWindowTitle("Extract!")
797
- msgBox.setText(
798
- "Are you sure you want to quit?")
799
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
800
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
801
- msgBox.exec()
802
-
803
- if msgBox.result() == QtWidgets.QMessageBox.Yes:
804
- # print(self.orgChoice.currentText())
805
- sys.exit()
806
- else:
807
- pass
808
- except Exception as e:
809
- show_error("Error in testexe() in main", e)
810
-
811
- def getData(self):
812
- try:
813
- try:
814
- self.orgChoice.currentIndexChanged.disconnect()
815
- except Exception as e:
816
- pass
817
-
818
- self.orgChoice.clear()
819
- self.endoChoice.clear()
820
- mypath = os.getcwd()
821
- found = False
822
- self.dbpath = mypath
823
- onlyfiles = [str(f) for f in os.listdir(mypath) if os.path.isfile(os.path.join(mypath, f))]
824
- onlyfiles.sort(key=str.lower)
825
- self.organisms_to_files = {}
826
- self.organisms_to_endos = {}
827
- first = True
828
- for file in onlyfiles:
829
- if file.find('.cspr') != -1:
830
- if first == True:
831
- first = False
832
- found = True
833
- newname = file[0:-4]
834
- endo = newname[newname.rfind("_")+1:-1]
835
- hold = open(file, 'r')
836
- buf = (hold.readline())
837
- buf = str(buf)
838
- buf = buf.strip()
839
- species = buf.replace("GENOME: ",'')
840
-
841
- if species in self.organisms_to_files:
842
- self.organisms_to_files[species][endo] = [file, file.replace(".cspr", "_repeats.db")]
843
- else:
844
- self.organisms_to_files[species] = {}
845
- self.organisms_to_files[species][endo] = [file, file.replace(".cspr", "_repeats.db")]
846
-
847
- if species in self.organisms_to_endos:
848
- self.organisms_to_endos[species].append(endo)
849
- else:
850
- self.organisms_to_endos[species] = [endo]
851
- if self.orgChoice.findText(species) == -1:
852
- self.orgChoice.addItem(species)
853
-
854
- #self.orgChoice.addItem("Custom Input Sequences")
855
- # auto fill the kegg search bar with the first choice in orgChoice
856
- if found == False:
857
- return False
858
-
859
- self.endoChoice.clear()
860
- self.endoChoice.addItems(self.organisms_to_endos[str(self.orgChoice.currentText())])
861
- self.orgChoice.currentIndexChanged.connect(self.changeEndos)
862
- except Exception as e:
863
- show_error("Error in getData() in main.", e)
864
-
865
- def changeEndos(self):
866
- try:
867
- if self.orgChoice.currentText() != "Custom Input Sequences":
868
- self.Step2.setEnabled(True)
869
- self.endoChoice.setEnabled(True)
870
- self.radioButton_Gene.show()
871
- self.radioButton_Position.show()
872
- self.endoChoice.clear()
873
- self.endoChoice.addItems(self.organisms_to_endos[str(self.orgChoice.currentText())])
874
- else:
875
- self.Step2.setEnabled(False)
876
- self.endoChoice.clear()
877
- self.endoChoice.setEnabled(False)
878
- self.radioButton_Gene.hide()
879
- self.radioButton_Position.hide()
880
- except Exception as e:
881
- show_error("Error in changeEndos() in main", e)
882
-
883
- def change_directory(self):
884
- try:
885
- mydir = QtWidgets.QFileDialog.getExistingDirectory(
886
- None, "Open a folder...", self.dbpath, QtWidgets.QFileDialog.ShowDirsOnly)
887
-
888
- if not os.path.isdir(mydir):
889
- show_message(
890
- fontSize=12,
891
- icon=QtWidgets.QMessageBox.Icon.Critical,
892
- title="Not a directory",
893
- message="The directory you selected does not exist."
894
- )
895
- return
896
-
897
- if not any(file.endswith(".cspr") for file in os.listdir(mydir)):
898
- show_message(
899
- fontSize=12,
900
- icon=QtWidgets.QMessageBox.Icon.Critical,
901
- title="Directory is invalid!",
902
- message="You must select a directory with CSPR Files!"
903
- )
904
- return
905
-
906
- os.chdir(mydir)
907
- mydir = mydir.replace("/", "\\") if platform.system() == "Windows" else mydir
908
- GlobalSettings.CSPR_DB = mydir
909
-
910
- GlobalSettings.MTWin.directory = mydir
911
- GlobalSettings.MTWin.get_data()
912
- GlobalSettings.pop_Analysis.get_data()
913
- self.getData()
914
- self.fill_annotation_dropdown()
915
- except Exception as e:
916
- show_error("Error in change_directory() in main.", e)
917
-
918
- def changeto_multitargeting(self):
919
- try:
920
- os.chdir(os.getcwd())
921
- if GlobalSettings.MTWin.first_show == True:
922
- GlobalSettings.MTWin.show()
923
- GlobalSettings.MTWin.first_show = False
924
- else:
925
- GlobalSettings.MTWin.show()
926
- GlobalSettings.mainWindow.hide()
927
-
928
- except Exception as e:
929
- show_error("Error in changeto_multitargeting() in main.", e)
930
-
931
- #change to population analysis window
932
- def changeto_population_Analysis(self):
933
- try:
934
- GlobalSettings.pop_Analysis.launch()
935
- if GlobalSettings.pop_Analysis.first_show == True:
936
- center_ui(GlobalSettings.pop_Analysis)
937
- GlobalSettings.pop_Analysis.first_show = False
938
- GlobalSettings.pop_Analysis.show()
939
- GlobalSettings.mainWindow.hide()
940
- except Exception as e:
941
- show_error("Error in changeto_population_Analysis() in main.", e)
942
-
943
- def annotation_information(self):
944
- try:
945
- info = "Annotation files are used for searching for spacers on a gene/locus basis and can be selected here using either " \
946
- "NCBI databases or a local file."
947
- msgBox = QtWidgets.QMessageBox()
948
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
949
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
950
- msgBox.setWindowTitle("Annotation Information")
951
- msgBox.setText(
952
- info)
953
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Ok)
954
- msgBox.exec()
955
-
956
- except Exception as e:
957
- show_error("Error in annotation_information() in main.", e)
958
-
959
- @QtCore.pyqtSlot()
960
- def view_results(self):
961
- try:
962
- #center results window on current screen
963
- if self.Results.first_show == True:
964
- self.Results.first_show = False
965
- self.Results.centerUI()
966
-
967
- self.Results.show()
968
- self.hide()
969
- except Exception as e:
970
- show_error("Error in view_results() in main", e)
971
-
972
-
973
-
974
- def closeFunction(self):
975
- try:
976
- # Attempt to close the NCBI window if it exists
977
- try:
978
- self.ncbi.close()
979
- except AttributeError:
980
- print("No NCBI window to close.")
981
-
982
- self.myClosingWindow.get_files()
983
- center_ui(self.myClosingWindow)
984
- self.myClosingWindow.show()
985
- except Exception as e:
986
- show_error("Error in closeFunction() in main", e)
987
-
988
- def close_app(self):
989
- try:
990
- # Attempt to close the NCBI window if it exists
991
- try:
992
- self.ncbi.close()
993
- except Exception as e:
994
- print("No NCBI window to close.")
995
-
996
- # Proceed with other closing operations
997
- self.closeFunction()
998
- self.close()
999
- except Exception as e:
1000
- show_error("Error in close_app() in main", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/GenBankParse.py DELETED
@@ -1,82 +0,0 @@
1
- __author__ = 'brianmendoza'
2
-
3
- from Bio import Entrez, SeqIO
4
- import webbrowser
5
- import re
6
- import os
7
-
8
-
9
- class GenBankFile:
10
-
11
- def __init__(self, organism):
12
- Entrez.email = "bmendoz1@vols.utk.edu"
13
- self.directory = "/Users/brianmendoza/Desktop/GenBank_files/"
14
- self.org = organism
15
-
16
- def setOrg(self, org):
17
- self.org = org
18
-
19
- def setDirectory(self, path, org):
20
- self.directory = path
21
- self.setOrg(org)
22
-
23
- def convertToFasta(self):
24
- orgfile = self.directory + self.org + ".gbff"
25
- output = "/Users/brianmendoza/Desktop/GenBank_files/FASTAs/" + self.org + ".fna"
26
- SeqIO.convert(orgfile, "genbank", output, "fasta")
27
-
28
- def parseAnnotation(self):
29
- gb_file = self.directory + self.org + ".gbff"
30
- records = SeqIO.parse(open(gb_file,"r"), "genbank")
31
-
32
- # create table for multi-targeting reference
33
- table = {}
34
- count = 0
35
- for record in records:
36
- count += 1
37
- chrmnumber = str(count)
38
- table[chrmnumber] = []
39
- for feature in record.features:
40
- if feature.type == 'CDS': # hopefully gene and CDS are the same
41
-
42
- # getting the location...
43
- loc = str(feature.location)
44
- out = re.findall(r"[\d]+", loc)
45
- start = out[0]
46
- end = out[1]
47
- if len(out) > 2: # to account for "joined" domains
48
- end = out[3]
49
-
50
- # locus_tag and product...
51
- if 'locus_tag' in feature.qualifiers:
52
- ltag = feature.qualifiers['locus_tag']
53
- elif 'gene' in feature.qualifiers:
54
- ltag = feature.qualifiers['gene']
55
- if 'product' not in feature.qualifiers:
56
- prod = feature.qualifiers['note']
57
- else:
58
- prod = feature.qualifiers['product']
59
- # adding it all up...
60
- tup = (start, end, ltag, prod)
61
- table[chrmnumber].append(tup)
62
- return table
63
-
64
- def getChromSequence(self, index):
65
- gb_file = self.directory + self.org + ".gbff"
66
- records = SeqIO.parse(open(gb_file,"r"), "genbank")
67
- count = 0
68
- for record in records:
69
- count += 1
70
- if count == index:
71
- cstr = record.seq
72
- return cstr
73
-
74
-
75
- class GffFile:
76
-
77
- def __init__(self, organism):
78
- self.directory = "/Users/brianmendoza/Desktop/GenBank_Files/"
79
- self.org = organism
80
-
81
-
82
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/NewEndonuclease.py DELETED
@@ -1,228 +0,0 @@
1
- import sys, os
2
- from PyQt5 import QtWidgets, uic, QtGui, QtCore, Qt
3
- import models.GlobalSettings as GlobalSettings
4
- from PyQt5.QtGui import QIntValidator
5
- import traceback
6
- import math
7
- from utils.ui import show_message, show_error, scale_ui, center_ui
8
-
9
- logger = GlobalSettings.logger
10
-
11
- class NewEndonuclease(QtWidgets.QMainWindow):
12
- def __init__(self):
13
- print("Initializing NewEndonuclease class")
14
- try:
15
- super(NewEndonuclease, self).__init__()
16
- uic.loadUi(GlobalSettings.appdir + 'ui/newendonuclease.ui', self)
17
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
18
- self.setWindowTitle('New Endonuclease')
19
- self.error = False
20
- pamFlag = False
21
-
22
- self.onList = []
23
- self.offList = []
24
-
25
- self.onList, self.offList = self.get_on_off_data() ### Call function to fill on- and off- data name lists
26
-
27
- for name in self.onList: ### Add on-target names to drop-down
28
- self.comboBox.addItem(str(name))
29
-
30
- for name in self.offList: ### Add off-target names to drop-down
31
- self.comboBox_2.addItem(str(name))
32
-
33
- self.submit_button.clicked.connect(self.submit)
34
- self.cancel_button.clicked.connect(self.cancel)
35
-
36
- ### Set up validators for input fields:
37
- reg_ex1 = QtCore.QRegExp("[^/\\\\_]+") # No slashes or underscores
38
- reg_ex2 = QtCore.QRegExp("[^/\\\\_\\s]+") # No slashes, underscores, or spaces
39
- reg_ex3 = QtCore.QRegExp("[acdefghiklmnpqrstvwyACDEFGHIKLMNPQRSTVWY\S]+") # Only approved PAM characters and no spaces
40
- input_validator1 = QtGui.QRegExpValidator(reg_ex1, self)
41
- input_validator2 = QtGui.QRegExpValidator(reg_ex2, self)
42
- input_validator3 = QtGui.QRegExpValidator(reg_ex3, self)
43
- self.organism_name.setValidator(input_validator1)
44
- self.abbreviation.setValidator(input_validator2)
45
- self.pam_sequence.setValidator(input_validator3)
46
-
47
- self.seed_length.setValidator(QIntValidator(0,30,self.seed_length))
48
- self.five_length.setValidator(QIntValidator(0,20,self.five_length))
49
- self.three_length.setValidator(QIntValidator(0,20,self.three_length))
50
-
51
- groupbox_style = """
52
- QGroupBox:title{subcontrol-origin: margin;
53
- left: 10px;
54
- padding: 0 5px 0 5px;}
55
- QGroupBox#groupBox{border: 2px solid rgb(111,181,110);
56
- border-radius: 9px;
57
- font: bold 14pt 'Arial';
58
- margin-top: 10px;}"""
59
-
60
- self.groupBox.setStyleSheet(groupbox_style)
61
- self.groupBox_2.setStyleSheet(groupbox_style.replace("groupBox","groupBox_2"))
62
- self.groupBox_3.setStyleSheet(groupbox_style.replace("groupBox","groupBox_3"))
63
-
64
- scale_ui(self, custom_scale_width=480, custom_scale_height=615)
65
- except Exception as e:
66
- show_error("Error initializing NewEndonuclease class.", e)
67
-
68
- #helper function for writing new endo information to CASPERinfo - used by submit()
69
- def writeNewEndonuclease(self, newEndonucleaseStr):
70
- try:
71
- with open(GlobalSettings.appdir + 'CASPERinfo', 'r') as f, open(GlobalSettings.appdir + "new_file", 'w+') as f1:
72
- for line in f:
73
- f1.write(line)
74
- if 'ENDONUCLEASES' in line:
75
- f1.write(newEndonucleaseStr + '\n') # Move f1.write(line) above, to write above instead
76
- os.remove(GlobalSettings.appdir + "CASPERinfo")
77
- os.rename(GlobalSettings.appdir + "new_file",
78
- GlobalSettings.appdir + "CASPERinfo") # Rename the new file
79
- except Exception as e:
80
- show_error("Error in writeNewEndonuclease() in New Endonuclease.", e)
81
-
82
- #submit new endo to CASPERinfo file
83
- def submit(self):
84
- try:
85
- # This is executed when the button is pressed
86
- name = str(self.organism_name.text())
87
- abbr = str(self.abbreviation.text())
88
- crisprtype = str(self.crispr_type.text())
89
- seed_len = str(self.seed_length.text())
90
- five_len = str(self.five_length.text())
91
- three_len = str(self.three_length.text())
92
- pam = str(self.pam_sequence.text()).upper()
93
- ### Check for multiple PAMs and format if present
94
- if len(pam.split(','))>0:
95
- pam = [x.strip() for x in pam.split(',')]
96
- pam = ",".join(pam)
97
- ### Check for PAM directionality
98
- if self.five_pam.isChecked():
99
- pam_dir = str(5)
100
- else:
101
- pam_dir = str(3)
102
- on_scoring = str(self.comboBox.currentText())
103
- off_scoring = str(self.comboBox_2.currentText())
104
- length = len(seed_len) + len(five_len) + len(three_len)
105
- argument_list = [abbr, pam, five_len, seed_len, three_len, pam_dir, name, crisprtype, on_scoring, off_scoring]
106
- validPAM = ('A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y')
107
- self.error = False;
108
-
109
- ### Error checking for PAM alphabet
110
- for letter in pam:
111
- if (letter not in validPAM):
112
- show_message(
113
- fontSize=12,
114
- icon=QtWidgets.QMessageBox.Icon.Critical,
115
- title="Invalid PAM",
116
- message="Invalid characters in PAM Sequence."
117
- )
118
- return True
119
- ### Error checking for filling out all fields
120
- for arg in argument_list:
121
- if ';' in arg:
122
- show_message(
123
- fontSize=12,
124
- icon=QtWidgets.QMessageBox.Icon.Critical,
125
- title="Invalid Semicolon",
126
- message="Invalid character used: ';'."
127
- )
128
- return True
129
- elif arg == "":
130
- show_message(
131
- fontSize=12,
132
- icon=QtWidgets.QMessageBox.Icon.Critical,
133
- title="Empty Field",
134
- message="Please fill in all fields."
135
- )
136
- return True
137
- else:
138
- pass
139
-
140
- ### Check for duplicate endo abbreviations
141
- for key in GlobalSettings.mainWindow.organisms_to_endos:
142
- endo = GlobalSettings.mainWindow.organisms_to_endos[key]
143
- if abbr in endo:
144
- show_message(
145
- fontSize=12,
146
- icon=QtWidgets.QMessageBox.Icon.Critical,
147
- title="Duplicate endo name.",
148
- message="The given abbreviation already exists. Please choose a unique identifier."
149
- )
150
- return True
151
- else:
152
- pass
153
-
154
- myString = ""
155
- for i, arg in enumerate(argument_list):
156
- if i == len(argument_list)-1: ### Last argument in list
157
- myString += str(arg)
158
- else:
159
- myString += str(arg) + ";"
160
-
161
- self.writeNewEndonuclease(myString)
162
-
163
- ### Refresh endonuclease dropdown in New Genome
164
- GlobalSettings.mainWindow.newGenome.fillEndo()
165
-
166
- self.clear_all()
167
- self.close()
168
- except Exception as e:
169
- show_error("Error in submit() in New Endonuclease.", e)
170
-
171
- #cancel and close window
172
- def cancel(self):
173
- try:
174
- self.clear_all()
175
- self.close()
176
- except Exception as e:
177
- show_error("Error in cancel() in New Endonuclease.", e)
178
-
179
- # This function clears all of the line edits
180
- def clear_all(self):
181
- try:
182
- self.organism_name.clear()
183
- self.abbreviation.clear()
184
- self.crispr_type.clear()
185
- self.seed_length.clear()
186
- self.five_length.clear()
187
- self.three_length.clear()
188
- self.pam_sequence.clear()
189
- except Exception as e:
190
- show_error("Error in clear_all() in New Endonuclease.", e)
191
-
192
- # This function parses CASPERinfo to return the names (in lists) of all on-target and off-target scoring data
193
- def get_on_off_data(self):
194
- try:
195
- filename = GlobalSettings.appdir + "CASPERinfo"
196
- retList_on = []
197
- retList_off = []
198
- with open(filename, 'r') as f:
199
- lines = f.readlines()
200
- for i, line in enumerate(lines):
201
- line = str(line)
202
- if "ON-TARGET DATA" in line:
203
- index = i
204
- while "-----" not in line:
205
- if "DATA:" in line:
206
- retList_on.append(line.split("DATA:")[-1].strip()) ### Append name of scoring data to on-target name list
207
- line = lines[index+1]
208
- index += 1
209
- else:
210
- line = lines[index+1]
211
- index += 1
212
- continue
213
- elif "OFF-TARGET MATRICES" in line:
214
- index = i
215
- while "-----" not in line:
216
- if "MATRIX:" in line:
217
- retList_off.append(line.split("MATRIX:")[-1].strip()) ### Append name of scoring data to off-target name list
218
- line = lines[index+1]
219
- index += 1
220
- else:
221
- line = lines[index+1]
222
- index += 1
223
- continue
224
- else:
225
- continue
226
- return retList_on, retList_off
227
- except Exception as e:
228
- show_error("Error in get_on_off_data() in New Endonuclease.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/NewGenome.py DELETED
@@ -1,705 +0,0 @@
1
- from ast import Global
2
- import os
3
- from PyQt5 import QtWidgets, uic, QtGui, QtCore, Qt
4
- import models.GlobalSettings as GlobalSettings
5
- from functools import partial
6
- from utils.Algorithms import SeqTranslate
7
- import webbrowser
8
- import platform
9
- import traceback
10
- import math
11
- from utils.ui import show_message, show_error, scale_ui, center_ui
12
- from utils.web import ncbi_page, repo_page
13
-
14
- logger = GlobalSettings.logger
15
-
16
- def iter_except(function, exception):
17
- """Works like builtin 2-argument `iter()`, but stops on `exception`."""
18
- try:
19
- while True:
20
- yield function()
21
- except exception:
22
- return
23
-
24
- #UI prompt for when the user has finished running jobs in new genome to allow them to choose where the want to proceed
25
- class goToPrompt(QtWidgets.QMainWindow):
26
- def __init__(self):
27
- try:
28
- super(goToPrompt, self).__init__()
29
- uic.loadUi(GlobalSettings.appdir + 'ui/newgenomenavigationpage.ui', self)
30
-
31
- groupbox_style = """
32
- QGroupBox:title{subcontrol-origin: margin;
33
- left: 10px;
34
- padding: 0 5px 0 5px;}
35
- QGroupBox#groupBox{border: 2px solid rgb(111,181,110);
36
- border-radius: 9px;
37
- font: bold 14pt 'Arial';
38
- margin-top: 10px;}"""
39
- self.groupBox.setStyleSheet(groupbox_style)
40
- scale_ui(self, custom_scale_width=575, custom_scale_height=175)
41
- self.setWindowTitle("New Genome")
42
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
43
- self.hide()
44
-
45
- except Exception as e:
46
- show_error("Unable to initialize goToPrompt class in New Genome.", e)
47
-
48
- #New genome class to allow users to generate new CSPR files
49
- class NewGenome(QtWidgets.QMainWindow):
50
- def __init__(self, info_path):
51
- try:
52
- super(NewGenome, self).__init__()
53
- uic.loadUi(GlobalSettings.appdir + 'ui/NewGenome.ui', self)
54
- self.setWindowTitle('New Genome')
55
- self.setWindowTitle('New Genome')
56
- self.info_path = info_path
57
-
58
- #---Style Modifications---#
59
-
60
- groupbox_style = """
61
- QGroupBox:title{subcontrol-origin: margin;
62
- left: 10px;
63
- padding: 0 5px 0 5px;}
64
- QGroupBox#Step1{border: 2px solid rgb(111,181,110);
65
- border-radius: 9px;
66
- font: bold 14pt 'Arial';
67
- margin-top: 10px;}"""
68
-
69
- self.Step1.setStyleSheet(groupbox_style)
70
- self.Step2.setStyleSheet(groupbox_style.replace("Step1","Step2"))
71
- self.Step3.setStyleSheet(groupbox_style.replace("Step1","Step3"))
72
-
73
- #---Button Modifications---#
74
-
75
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
76
- self.resetButton.clicked.connect(self.reset)
77
- self.submitButton.clicked.connect(self.submit)
78
- self.browseForFile.clicked.connect(self.selectFasta)
79
- self.remove_job.clicked.connect(self.remove_from_queue)
80
- self.output_browser.setText("Waiting for program initiation...")
81
- self.contButton.clicked.connect(self.continue_to_main)
82
-
83
- self.comboBoxEndo.currentIndexChanged.connect(self.endo_settings)
84
-
85
- self.runButton.clicked.connect(self.run_jobs_wrapper)
86
- self.clearButton.clicked.connect(self.clear_all)
87
-
88
- self.JobsQueue = [] # holds Job classes.
89
- self.check_strings = []
90
- self.Endos = dict()
91
- self.file = ""
92
-
93
- self.process = QtCore.QProcess()
94
- self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
95
- self.process.finished.connect(self.upon_process_finishing)
96
- self.seqTrans = SeqTranslate()
97
- self.exit = False
98
-
99
- self.first = False
100
- #show functionalities on window
101
- self.fillEndo()
102
-
103
- self.num_chromo_next = False
104
-
105
- #Jobs Table
106
- self.job_Table.setShowGrid(False)
107
- self.job_Table.horizontalHeader().setSectionsClickable(True)
108
- self.job_Table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
109
- self.job_Table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
110
- self.job_Table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
111
- self.job_Table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
112
- self.fin_index=0
113
-
114
- self.mwfg = self.frameGeometry() ##Center window
115
- self.cp = QtWidgets.QDesktopWidget().availableGeometry().center() ##Center window
116
- self.total_chrom_count = 0
117
- self.perc_increase = 0
118
- self.progress = 0
119
-
120
- #toolbar button actions
121
- self.visit_repo.triggered.connect(repo_page)
122
- self.go_ncbi.triggered.connect(ncbi_page)
123
-
124
- self.comboBoxEndo.currentIndexChanged.connect(self.changeEndos)
125
-
126
- ### NCBI tool
127
- self.NCBI_File_Search.clicked.connect(self.open_ncbi_tool)
128
-
129
- self.seed_length.setEnabled(False)
130
- self.five_length.setEnabled(False)
131
- self.three_length.setEnabled(False)
132
- self.repeats_box.setEnabled(False)
133
-
134
- ### User prompt class
135
- self.goToPrompt = goToPrompt()
136
- self.goToPrompt.goToMain.clicked.connect(self.continue_to_main)
137
- self.goToPrompt.goToMT.clicked.connect(self.continue_to_MT)
138
- self.goToPrompt.goToPop.clicked.connect(self.continue_to_pop)
139
-
140
- self.orgName.setFocus()
141
-
142
- ### Connect New endonuclease to New Genome
143
- self.actionUpload_New_Endonuclease.triggered.connect(self.launch_newEndonuclease)
144
-
145
- ### Set up validators for input fields:
146
- reg_ex1 = QtCore.QRegExp("[^/\\\\_]+") # No slashes or underscores
147
- reg_ex2 = QtCore.QRegExp("\\S+")
148
- input_validator1 = QtGui.QRegExpValidator(reg_ex1, self)
149
- input_validator2 = QtGui.QRegExpValidator(reg_ex2, self)
150
- self.orgName.setValidator(input_validator1)
151
- self.strainName.setValidator(input_validator1)
152
- self.orgCode.setValidator(input_validator2)
153
-
154
- scale_ui(self, custom_scale_width=850, custom_scale_height=750)
155
- self.first_show = True
156
- except Exception as e:
157
- show_error("Error initializing New Genome class.", e)
158
-
159
- def launch_newEndonuclease(self):
160
- try:
161
- GlobalSettings.mainWindow.getData()
162
- GlobalSettings.mainWindow.newEndonuclease.centerUI()
163
- GlobalSettings.mainWindow.newEndonuclease.show()
164
- GlobalSettings.mainWindow.newEndonuclease.activateWindow()
165
- except Exception as e:
166
- show_error("Error in launch_newEndonuclease() in New Genome.", e)
167
-
168
- #open the ncbi search tool window
169
- def open_ncbi_tool(self):
170
- try:
171
- #center ncbi on current screen
172
- if GlobalSettings.mainWindow.ncbi.first_show == True:
173
- GlobalSettings.mainWindow.ncbi.first_show = False
174
- GlobalSettings.mainWindow.ncbi.centerUI()
175
- if self.orgName.text() != "":
176
- GlobalSettings.mainWindow.ncbi.organism_line_edit.setText(self.orgName.text())
177
- if self.strainName.text() != "":
178
- GlobalSettings.mainWindow.ncbi.infra_name_line_edit.setText(self.strainName.text())
179
- GlobalSettings.mainWindow.ncbi.show()
180
- GlobalSettings.mainWindow.ncbi.activateWindow()
181
- except Exception as e:
182
- show_error("Error in open_ncbi_tool() in New Genome.", e)
183
-
184
- def remove_from_queue(self):
185
- try:
186
- while(True):
187
- indexes = self.job_Table.selectionModel().selectedRows()
188
- if len(indexes) == 0:
189
- break
190
- self.job_Table.removeRow(indexes[0].row())
191
- except Exception as e:
192
- show_error("Error in remove_from_queue() in New Genome.", e)
193
-
194
- #prompt user with file browser to select fasta/fna files
195
- def selectFasta(self):
196
- try:
197
- filed = QtWidgets.QFileDialog()
198
- myFile = QtWidgets.QFileDialog.getOpenFileName(filed, "Choose a File")
199
- if (myFile[0] != ""):
200
- if not myFile[0].endswith(".fa") and not myFile[0].endswith(".fna") and not myFile[0].endswith(".fasta"):
201
- show_message(
202
- fontSize=12,
203
- icon=QtWidgets.QMessageBox.Icon.Critical,
204
- title="File Selection Error",
205
- message="You have selected an incorrect type of file. Please choose a FASTA/FNA file."
206
- )
207
- return
208
- else:
209
- self.file = myFile[0]
210
- self.selectedFile.setText(str(myFile[0]))
211
- except Exception as e:
212
- show_error("Error in selectFasta() in New Genome.", e)
213
-
214
- #submit jobs to queue
215
- def submit(self):
216
- try:
217
- warning = ""
218
- if len(self.orgName.text()) == 0:
219
- warning = warning + "You need to include the organism's name."
220
- if len(self.file) == 0:
221
- warning = warning + "You need to select a file."
222
- if len(warning) != 0:
223
- show_message(
224
- fontSize=12,
225
- icon=QtWidgets.QMessageBox.Icon.Critical,
226
- title="Required Information",
227
- message=warning
228
- )
229
- return
230
- if len(self.strainName.text()) == 0:
231
- warning = warning + "\nIt is recommended to include the organism's subspecies/strain."
232
- if len(self.orgCode.text()) == 0:
233
- warning = warning + "\nYou must include an organism code."
234
- if len(warning) != 0:
235
- msgBox = QtWidgets.QMessageBox()
236
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
237
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
238
- msgBox.setWindowTitle("Missing Information")
239
- msgBox.setText(warning + "\n\nDo you wish to continue without including this information?")
240
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
241
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
242
- msgBox.exec()
243
-
244
- if msgBox.result() == QtWidgets.QMessageBox.No:
245
- return
246
-
247
- #endo, pam, repeats, directionality, five length, seed length, three length, orgcode, output path, CASPERinfo path, fna path, orgName, notes, on target matrix
248
- args = self.Endos[self.comboBoxEndo.currentText()][0]
249
- args += " " + self.Endos[self.comboBoxEndo.currentText()][1]
250
- if self.mt.isChecked():
251
- args += " " + "TRUE"
252
- else:
253
- args += " " + "FALSE"
254
-
255
- if self.Endos[self.comboBoxEndo.currentText()][5] == "3":
256
- args += " " + "FALSE"
257
- else:
258
- args += " " + "TRUE"
259
-
260
- if self.repeats_box.isChecked():
261
- args += " " + "TRUE"
262
- else:
263
- args += " " + "FALSE"
264
-
265
- args += " " + self.Endos[self.comboBoxEndo.currentText()][2]
266
- args += " " + self.Endos[self.comboBoxEndo.currentText()][3]
267
- args += " " + self.Endos[self.comboBoxEndo.currentText()][4]
268
- args += " " + self.orgCode.text()
269
- if platform.system() == 'Windows':
270
- args += " " + '"' + GlobalSettings.CSPR_DB.replace("/","\\") + '\\"'
271
- args += " " + '"' + GlobalSettings.appdir.replace("/","\\") + "CASPERinfo" + '"'
272
- args += " " + '"' + self.file.replace("/","\\") + '"'
273
- else:
274
- args += " " + '"' + GlobalSettings.CSPR_DB.replace("\\","/") + '/"'
275
- args += " " + '"' + GlobalSettings.appdir.replace("\\","/") + "CASPERinfo" + '"'
276
- args += " " + '"' + self.file.replace("\\","/") + '"'
277
-
278
- args += " " + '"' + self.orgName.text() + " " + self.strainName.text() + '"'
279
- args += " " + '"' + "notes" + '"'
280
- args += " " + '"DATA:' + self.Endos[self.comboBoxEndo.currentText()][6] + '"'
281
-
282
- tmp = self.orgName.text()+ " " + self.strainName.text() + " " + self.Endos[self.comboBoxEndo.currentText()][0] + " " + self.orgCode.text()
283
- if tmp in self.check_strings:
284
- show_message(
285
- fontSize=12,
286
- icon=QtWidgets.QMessageBox.Icon.Critical,
287
- title="Duplicate Entry",
288
- message="You have submitted a duplicate entry. Consider changing the organism code or strain name to differentiate closely related strains."
289
- )
290
- return
291
- name = self.orgCode.text() + "_" + str(self.Endos[self.comboBoxEndo.currentText()][0])
292
- rowPosition = self.job_Table.rowCount()
293
- self.job_Table.insertRow(rowPosition)
294
- item = QtWidgets.QTableWidgetItem(name)
295
- item.setTextAlignment(QtCore.Qt.AlignHCenter)
296
- self.job_Table.setItem(rowPosition, 0, item)
297
- self.check_strings.append(tmp)
298
- self.JobsQueue.append(args)
299
- except Exception as e:
300
- show_error("Error in submit() in New Genome.", e)
301
-
302
- #fill the endo dropdown
303
- def fillEndo(self):
304
- try:
305
- #disconnect signal
306
- try:
307
- self.comboBoxEndo.currentIndexChanged.disconnect()
308
- except:
309
- pass
310
-
311
- #clear out the endo box
312
- self.comboBoxEndo.clear()
313
-
314
- f = open(GlobalSettings.appdir + "CASPERinfo")
315
- while True:
316
- line = f.readline()
317
- if line.startswith('ENDONUCLEASES'):
318
- while True:
319
- line = f.readline()
320
- if (line[0] == "-"):
321
- break
322
- line_tokened = line.split(";")
323
- if len(line_tokened) == 10:
324
- endo = line_tokened[0]
325
- # Checking to see if there is more than one pam sequence in the list
326
- if line_tokened[1].find(",") != -1:
327
- p_pam = line_tokened[1].split(",")[0]
328
- else:
329
- p_pam = line_tokened[1]
330
- five_length = line_tokened[2]
331
- seed_length = line_tokened[3]
332
- three_length = line_tokened[4]
333
- dir = line_tokened[5]
334
- on_target_data = line_tokened[8]
335
- self.Endos[endo + " - PAM: " + p_pam] = (endo, p_pam, five_length, seed_length, three_length, dir, on_target_data)
336
- break
337
- f.close()
338
- self.comboBoxEndo.addItems(self.Endos.keys())
339
- key = list(self.Endos.keys())[0]
340
- self.seed_length.setText(self.Endos[key][3])
341
- self.five_length.setText(self.Endos[key][2])
342
- self.three_length.setText(self.Endos[key][4])
343
-
344
- #reconnect signal
345
- self.comboBoxEndo.currentIndexChanged.connect(self.changeEndos)
346
- except Exception as e:
347
- show_error("Error in fillEndo() in New Genome.", e)
348
-
349
- #event handler for endo changing - update endo length data
350
- def changeEndos(self):
351
- try:
352
- key = str(self.comboBoxEndo.currentText())
353
- self.seed_length.setText(self.Endos[key][3])
354
- self.five_length.setText(self.Endos[key][2])
355
- self.three_length.setText(self.Endos[key][4])
356
- except Exception as e:
357
- show_error("Error in changeEndos() in New Genome.", e)
358
-
359
- #check if endo is 3' or 5'
360
- def endo_settings(self):
361
- try:
362
- # check the if it's 3' or 5', and check the box accordingly
363
- if int(self.seqTrans.endo_info[self.Endos[self.comboBoxEndo.currentText()][0]][3]) == 3:
364
- self.pamBox.setChecked(0)
365
- elif int(self.seqTrans.endo_info[self.Endos[self.comboBoxEndo.currentText()][0]][3]) == 5:
366
- self.pamBox.setChecked(1)
367
- except Exception as e:
368
- show_error("Error in endo_settings() in New Genome.", e)
369
-
370
- #wrapper for running jobs
371
- def run_jobs_wrapper(self):
372
- try:
373
- self.indexes = []
374
- self.job_Table.selectAll()
375
- indexes = self.job_Table.selectionModel().selectedRows()
376
- for index in sorted(indexes):
377
- if self.job_Table.item(index.row(), 0).text() != "":
378
- self.indexes.append(index.row())
379
- self.run_job()
380
- except Exception as e:
381
- show_error("Error in run_jobs_wrapper() in New Genome.", e)
382
-
383
- #run job in queue
384
- def run_job(self):
385
- try:
386
- if len(self.indexes) > 0:
387
- self.progressBar.setValue(0)
388
- self.progress = 0
389
- row_index = self.indexes[0]
390
- name = self.job_Table.item(row_index, 0).text()
391
- item = QtWidgets.QTableWidgetItem(name)
392
- item.setTextAlignment(QtCore.Qt.AlignHCenter)
393
- self.job_Table.setItem(row_index, 1, item)
394
- self.job_Table.setItem(row_index, 0, QtWidgets.QTableWidgetItem(""))
395
-
396
- def output_stdout(p):
397
- line = str(p.readAll())
398
- line = line[2:]
399
- line = line[:len(line) - 1]
400
- for lines in line.split(r"\n"):
401
- lines = lines.rstrip("\n")
402
- lines = lines.rstrip("\r")
403
- lines = lines.rstrip(r"\n")
404
- lines = lines.rstrip(r"\r")
405
- lines = lines.rstrip("\r\n")
406
- lines = lines.rstrip(r"\r\n")
407
- if lines != "":
408
- if lines.find("Number of Chromosomes/Scaffolds") != -1:
409
- copy = lines
410
- copy = copy.replace(" ","")
411
- copy = copy[copy.find(":")+1:]
412
- self.total_chrom_count = int(copy)
413
- self.perc_increase = ((1 / (2 * self.total_chrom_count)) * 70)
414
- self.progressBar.setValue(20)
415
- self.progress = 20
416
- elif lines.find("complete.") != -1:
417
- self.progress += self.perc_increase
418
- self.progressBar.setValue(int(self.progress))
419
- elif lines.find("Processing Targets.") != -1:
420
- self.progress = 70
421
- self.progressBar.setValue(int(self.progress))
422
- elif lines.find("Writing out uniques.") != -1:
423
- self.progress = 90
424
- self.progressBar.setValue(int(self.progress))
425
- elif lines.find("Writing out repeats.") != -1:
426
- self.progress = 95
427
- self.progressBar.setValue(int(self.progress))
428
- elif lines == "Finished.":
429
- self.progress = 100
430
- self.progressBar.setValue(int(self.progress))
431
- self.output_browser.append(lines)
432
-
433
- job_args = self.JobsQueue[row_index]
434
- if platform.system() == 'Windows':
435
- program = '"' + GlobalSettings.appdir + "SeqFinderFolder/Casper_Seq_Finder_Win.exe" + '" '
436
- elif platform.system() == 'Linux':
437
- program = '"' + GlobalSettings.appdir + "SeqFinderFolder/Casper_Seq_Finder_Lin" + '" '
438
- else:
439
- program = '"' + GlobalSettings.appdir + "SeqFinderFolder/Casper_Seq_Finder_Mac" + '" '
440
- program += job_args
441
- self.process.readyReadStandardOutput.connect(partial(output_stdout, self.process))
442
- self.process.start(program)
443
- else:
444
- show_message(
445
- fontSize=12,
446
- icon=QtWidgets.QMessageBox.Icon.Critical,
447
- title="No Jobs To Run",
448
- message="No jobs are in the queue to run. Please add a job before running."
449
- )
450
- except Exception as e:
451
- show_error("Error in run_job() in New Genome.", e)
452
-
453
- #even handler for when jobs finish execution
454
- def upon_process_finishing(self):
455
- try:
456
- row_index = self.indexes[0]
457
- name = self.job_Table.item(row_index, 1).text()
458
- item = QtWidgets.QTableWidgetItem(name)
459
- item.setTextAlignment(QtCore.Qt.AlignHCenter)
460
- self.job_Table.setItem(row_index, 2, item)
461
- self.job_Table.setItem(row_index, 1, QtWidgets.QTableWidgetItem(""))
462
- self.indexes.pop(0)
463
- if len(self.indexes) != 0:
464
- self.run_job()
465
- else:
466
- #prompt user if they want to analyze their new files
467
- center_ui(self.goToPrompt)
468
- self.goToPrompt.show()
469
- self.goToPrompt.activateWindow()
470
- except Exception as e:
471
- show_error("Error in upon_process_finishing() in New Genome.", e)
472
-
473
- #clear the job table
474
- def clear_all(self):
475
- try:
476
- self.process.kill()
477
- self.fin_index = 0
478
- self.job_Table.clearContents()
479
- self.job_Table.setRowCount(0)
480
- self.JobsQueue = []
481
- self.check_strings = []
482
- self.output_browser.clear()
483
- self.output_browser.setText("Waiting for program initiation...")
484
- self.orgName.clear()
485
- self.strainName.clear()
486
- self.orgCode.clear()
487
- self.selectedFile.clear()
488
- self.selectedFile.setPlaceholderText("Selected FASTA/FNA File")
489
- self.progressBar.setValue(0)
490
- self.first = False
491
- except Exception as e:
492
- show_error("Error in clear_all() in New Genome.", e)
493
-
494
- #reset the whole form
495
- def reset(self):
496
- try:
497
- self.orgName.clear()
498
- self.strainName.clear()
499
- self.orgCode.clear()
500
- self.selectedFile.clear()
501
- self.selectedFile.setPlaceholderText("Selected FASTA/FNA File")
502
- self.output_browser.clear()
503
- self.output_browser.setText("Waiting for program initiation...")
504
- self.file = ""
505
- except Exception as e:
506
- show_error("Error in reset() in New Genome.", e)
507
-
508
- #event handler for user wanting to close the window
509
- def closeEvent(self, event):
510
- try:
511
- # make sure that there are cspr files in the DB
512
- file_names = os.listdir(GlobalSettings.CSPR_DB)
513
- noCSPRFiles = True
514
- for file in file_names:
515
- if 'cspr' in file:
516
- noCSPRFiles = False
517
- break
518
- if noCSPRFiles == True:
519
- if self.exit == False:
520
- msgBox = QtWidgets.QMessageBox()
521
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
522
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
523
- msgBox.setWindowTitle("No CSPR file generated")
524
- msgBox.setText("No CSPR file has been generated, thus the main program cannot run. Please create a CSPR file."
525
- "Alternatively, you could quit the program. Would you like to quit?")
526
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
527
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
528
- msgBox.exec()
529
-
530
- if (msgBox.result() == QtWidgets.QMessageBox.No):
531
- event.ignore()
532
- else:
533
- event.accept()
534
- else:
535
- self.exit = False
536
- event.accept()
537
- else:
538
- self.process.kill()
539
- self.clear_all()
540
- self.goToPrompt.hide()
541
- GlobalSettings.mainWindow.fill_annotation_dropdown()
542
- if GlobalSettings.mainWindow.orgChoice.currentText() != '':
543
- GlobalSettings.mainWindow.orgChoice.currentIndexChanged.disconnect()
544
- GlobalSettings.mainWindow.orgChoice.clear()
545
- GlobalSettings.mainWindow.endoChoice.clear()
546
- GlobalSettings.mainWindow.getData()
547
- GlobalSettings.MTWin.launch()
548
- GlobalSettings.pop_Analysis.launch()
549
-
550
- if GlobalSettings.mainWindow.first_show == True:
551
- GlobalSettings.mainWindow.first_show = False
552
- GlobalSettings.mainWindow.centerUI()
553
- GlobalSettings.mainWindow.show()
554
- event.accept()
555
- except Exception as e:
556
- show_error("Error in closeEvent() in New Genome.", e)
557
-
558
- #event handler for user wanting to go to Main once jobs complete
559
- def continue_to_main(self):
560
- try:
561
- # make sure that there are cspr files in the DB
562
- file_names = os.listdir(GlobalSettings.CSPR_DB)
563
- noCSPRFiles = True
564
- for file in file_names:
565
- if 'cspr' in file:
566
- noCSPRFiles = False
567
- break
568
- if noCSPRFiles == True:
569
-
570
- msgBox = QtWidgets.QMessageBox()
571
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
572
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
573
- msgBox.setWindowTitle("No CSPR file generated")
574
- msgBox.setText(
575
- "No CSPR file has been generated, thus the main program cannot run. Please create a CSPR file."
576
- "Alternatively, you could quit the program. Would you like to quit?")
577
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
578
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
579
- msgBox.exec()
580
-
581
- if (msgBox.result() == QtWidgets.QMessageBox.Yes):
582
- self.exit = True
583
- self.close()
584
- else:
585
- self.process.kill()
586
- self.clear_all()
587
- self.goToPrompt.hide()
588
- GlobalSettings.mainWindow.fill_annotation_dropdown()
589
- if GlobalSettings.mainWindow.orgChoice.currentText() != '':
590
- GlobalSettings.mainWindow.orgChoice.currentIndexChanged.disconnect()
591
- GlobalSettings.mainWindow.orgChoice.clear()
592
- GlobalSettings.mainWindow.endoChoice.clear()
593
- GlobalSettings.mainWindow.getData()
594
- GlobalSettings.MTWin.launch()
595
- GlobalSettings.pop_Analysis.launch()
596
-
597
- # center main on current screen
598
- if GlobalSettings.mainWindow.first_show == True:
599
- GlobalSettings.mainWindow.first_show = False
600
- center_ui(GlobalSettings.mainWindow)
601
- GlobalSettings.mainWindow.show()
602
- self.hide()
603
- except Exception as e:
604
- show_error("Error in continue_to_main() in New Genome.", e)
605
-
606
- #event handler for user wanting to go to multi-targeting once jobs complete
607
- def continue_to_MT(self):
608
- try:
609
- # make sure that there are cspr files in the DB
610
- file_names = os.listdir(GlobalSettings.CSPR_DB)
611
- noCSPRFiles = True
612
- for file in file_names:
613
- if 'cspr' in file:
614
- noCSPRFiles = False
615
- break
616
- if noCSPRFiles == True:
617
-
618
- msgBox = QtWidgets.QMessageBox()
619
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
620
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
621
- msgBox.setWindowTitle("No CSPR file generated")
622
- msgBox.setText(
623
- "No CSPR file has been generated, thus the main program cannot run. Please create a CSPR file."
624
- "Alternatively, you could quit the program. Would you like to quit?")
625
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
626
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
627
- msgBox.exec()
628
-
629
-
630
-
631
- if (msgBox.result() == QtWidgets.QMessageBox.Yes):
632
- self.exit = True
633
- self.close()
634
-
635
- else:
636
- self.process.kill()
637
- self.clear_all()
638
- self.goToPrompt.hide()
639
- GlobalSettings.mainWindow.fill_annotation_dropdown()
640
- if GlobalSettings.mainWindow.orgChoice.currentText() != '':
641
- GlobalSettings.mainWindow.orgChoice.currentIndexChanged.disconnect()
642
- GlobalSettings.mainWindow.orgChoice.clear()
643
- GlobalSettings.mainWindow.endoChoice.clear()
644
- GlobalSettings.mainWindow.getData()
645
- GlobalSettings.MTWin.launch()
646
- GlobalSettings.pop_Analysis.launch()
647
-
648
- # center multi-targeting on current screen
649
- if GlobalSettings.MTWin.first_show == True:
650
- GlobalSettings.MTWin.first_show = False
651
- GlobalSettings.MTWin.centerUI()
652
-
653
- GlobalSettings.MTWin.show()
654
- self.hide()
655
- except Exception as e:
656
- show_error("Error in continue_to_MT() in New Genome.", e)
657
-
658
- #event handler for user wanting to go to population analysis once jobs complete
659
- def continue_to_pop(self):
660
- try:
661
- # make sure that there are cspr files in the DB
662
- file_names = os.listdir(GlobalSettings.CSPR_DB)
663
- noCSPRFiles = True
664
- for file in file_names:
665
- if 'cspr' in file:
666
- noCSPRFiles = False
667
- break
668
- if noCSPRFiles == True:
669
-
670
- msgBox = QtWidgets.QMessageBox()
671
- msgBox.setStyleSheet("font: " + str(self.fontSize) + "pt 'Arial'")
672
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
673
- msgBox.setWindowTitle("No CSPR file generated")
674
- msgBox.setText(
675
- "No CSPR file has been generated, thus the main program cannot run. Please create a CSPR file."
676
- "Alternatively, you could quit the program. Would you like to quit?")
677
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
678
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
679
- msgBox.exec()
680
-
681
- if (msgBox.result() == QtWidgets.QMessageBox.Yes):
682
- self.exit = True
683
- self.close()
684
-
685
- else:
686
- self.process.kill()
687
- self.clear_all()
688
- self.goToPrompt.hide()
689
- GlobalSettings.mainWindow.fill_annotation_dropdown()
690
- if GlobalSettings.mainWindow.orgChoice.currentText() != '':
691
- GlobalSettings.mainWindow.orgChoice.currentIndexChanged.disconnect()
692
- GlobalSettings.mainWindow.orgChoice.clear()
693
- GlobalSettings.mainWindow.endoChoice.clear()
694
- GlobalSettings.mainWindow.getData()
695
- GlobalSettings.MTWin.launch()
696
- GlobalSettings.pop_Analysis.launch()
697
-
698
- if GlobalSettings.pop_Analysis.first_show == True:
699
- GlobalSettings.pop_Analysis.first_show = False
700
- GlobalSettings.pop_Analysis.centerUI()
701
-
702
- GlobalSettings.pop_Analysis.show()
703
- self.hide()
704
- except Exception as e:
705
- show_error("Error in continue_to_pop() in New Genome.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/StartupWindow.py DELETED
@@ -1,255 +0,0 @@
1
- import os
2
- import platform
3
- import traceback
4
- import logging
5
- from PyQt5 import QtGui, QtWidgets, QtCore, uic, Qt
6
- import models.GlobalSettings as GlobalSettings
7
- from utils.ui import show_message, show_error, scale_ui
8
-
9
- logger = GlobalSettings.logger
10
-
11
- class StartupWindow(QtWidgets.QMainWindow):
12
- def __init__(self):
13
- try:
14
- super(StartupWindow, self).__init__()
15
- try:
16
- uic.loadUi(GlobalSettings.appdir + 'ui/startupCASPER.ui', self)
17
- self.setWindowIcon(QtGui.QIcon(GlobalSettings.appdir + "cas9image.png"))
18
- except Exception as e:
19
- show_error("Unable to load UX files for Startup Window.", e)
20
-
21
- #set "Main" button to be the default highlighted button on startup
22
- self.goToMain.setDefault(True)
23
-
24
- #get current directory, and update based on current operating system
25
- self.currentDirectory = os.getcwd()
26
- self.databaseDirectory = self.loadDatabaseDirectory()
27
- GlobalSettings.CSPR_DB = self.databaseDirectory
28
- if platform.system() == "Windows":
29
- GlobalSettings.CSPR_DB = GlobalSettings.CSPR_DB.replace("/","\\")
30
- else:
31
- GlobalSettings.CSPR_DB = GlobalSettings.CSPR_DB.replace("\\","/")
32
-
33
- #setup event handlers for startup buttons
34
- self.currentDirText.setText(self.databaseDirectory)
35
- self.changeDir.clicked.connect(self.change_directory)
36
- self.goToMain.clicked.connect(self.launchMainWindow)
37
- self.goToNewGenome.clicked.connect(self.launchNewGenome)
38
-
39
- self.setWindowTitle("CASPER")
40
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
41
-
42
- scale_ui(self, custom_scale_width=1150, custom_scale_height=650)
43
-
44
- except Exception as e:
45
- show_error("Error initializing StartupWindow class.", e)
46
-
47
- #event handler for user clicking the "Change..." button - used for changing CASPER database directory
48
- def change_directory(self):
49
- try:
50
- # Launch OS file browser
51
- newDirectory = QtWidgets.QFileDialog.getExistingDirectory(
52
- self, "Open a folder...", self.databaseDirectory, QtWidgets.QFileDialog.ShowDirsOnly)
53
-
54
- # Check if selected path is a directory in the system
55
- if not os.path.isdir(newDirectory):
56
- show_message(
57
- fontSize=self.fontSize,
58
- icon=QtWidgets.QMessageBox.Icon.Critical,
59
- title="Not a directory",
60
- message="The directory you selected does not exist.",
61
- )
62
- return
63
-
64
- # Ensure directory contains correct filepath format based on OS
65
- newDirectory = newDirectory.replace("/", "\\") if platform.system() == "Windows" else newDirectory.replace("\\", "/")
66
-
67
- # Update text edit showing the current selected database directory
68
- self.currentDirText.setText(newDirectory)
69
-
70
- # Update CASPER database directories
71
- self.databaseDirectory = newDirectory
72
- GlobalSettings.CSPR_DB = newDirectory
73
-
74
- except Exception as e:
75
- show_error("change_directory() in startup window", e)
76
-
77
- #function for loading the default database directory specified in CASPERinfo
78
- #returns: default database parsed from CASPERinfo
79
- def loadDatabaseDirectory(self):
80
- casperInfoPath = os.path.join(GlobalSettings.appdir, "CASPERinfo")
81
- defaultDirectory = "Where would you like to store CASPER database files?" # Default message if directory not found
82
-
83
- try:
84
- with open(casperInfoPath, 'r') as file:
85
- for line in file:
86
- if 'DIRECTORY:' in line:
87
- defaultDirectory = line.strip().replace("DIRECTORY:", "").strip()
88
- break
89
-
90
- # Ensure the directory path is formatted correctly based on the operating system
91
- if platform.system() == "Windows":
92
- defaultDirectory = defaultDirectory.replace("/", "\\")
93
- else:
94
- defaultDirectory = defaultDirectory.replace("\\", "/")
95
-
96
- logger.debug("Successfully parsed CASPERinfo for default database directory.")
97
- return defaultDirectory
98
-
99
- except Exception as e:
100
- show_error(f"Error reading {casperInfoPath}: {e}", e)
101
-
102
- return defaultDirectory
103
-
104
- #function for saving the currently selected database directory to CASPERinfo to be the new default value on startup
105
- def saveDatabaseDirectory(self):
106
- try:
107
- #variable to hold the CASPERinfo data with new default directory change
108
- CASPERInfoNewData = ""
109
-
110
- #new default directory string for CASPERinfo
111
- newDefaultDirectory = "DIRECTORY:" + str(self.databaseDirectory)
112
-
113
- #open CASPERinfo file to read in the files data and add in new change
114
- try:
115
- CASPERInfo = open(GlobalSettings.appdir + "CASPERinfo", 'r+')
116
- CASPERinfoData = CASPERInfo.read()
117
- CASPERinfoData = CASPERinfoData.split('\n')
118
- for line in CASPERinfoData:
119
- #if directory line found, use new default directory string instead
120
- if 'DIRECTORY:' in line:
121
- CASPERInfoNewData = CASPERInfoNewData + "\n" + newDefaultDirectory
122
- else:
123
- CASPERInfoNewData = CASPERInfoNewData + "\n" + line
124
- CASPERInfoNewData = CASPERInfoNewData[1:]
125
-
126
- #close CASPERinfo
127
- CASPERInfo.close()
128
-
129
- #re-open the file and re-write it with current changes
130
- CASPERInfo = open(GlobalSettings.appdir + "CASPERinfo", 'w+')
131
- CASPERInfo.write(CASPERInfoNewData)
132
- CASPERInfo.close()
133
- logger.debug("Successfully updated CASPERinfo with new default database directory.")
134
- except Exception as e:
135
- show_error("Unable to write to CASPERinfo file to update database directory.", e)
136
- except Exception as e:
137
- show_error("Error in saveDatabaseDirectory() in startup window.", e)
138
-
139
- # Event handler for user clicking the "New Genome" button - used for launching New Genome
140
- def launchNewGenome(self):
141
- try:
142
- # Make sure database directory variable is up-to-date based on what the user has in the text edit
143
- self.databaseDirectory = str(self.currentDirText.text())
144
-
145
- if not os.path.isdir(self.databaseDirectory):
146
- show_message(
147
- fontSize=12,
148
- icon=QtWidgets.QMessageBox.Icon.Critical,
149
- title="Not a directory",
150
- message="The directory you selected does not exist.",
151
- )
152
- return
153
-
154
- # Change directories to the specified database directory provided
155
- os.chdir(self.databaseDirectory)
156
-
157
- # Write out the database directory to CASPERinfo to be the new default loaded value
158
- self.saveDatabaseDirectory()
159
-
160
- # Update global database variable
161
- GlobalSettings.CSPR_DB = self.databaseDirectory
162
-
163
- # Create app directories
164
- initialize_app_directories()
165
-
166
- # Launch New Genome window
167
- self.launch_new_genome()
168
-
169
- self.close()
170
- except Exception as e:
171
- show_error("launchNewGenome() in startup window", e)
172
-
173
- def launch_new_genome(self):
174
- try:
175
- GlobalSettings.mainWindow.launch_newGenome()
176
- logger.debug("Successfully initialized New Genome in startup window.")
177
- except Exception as e:
178
- show_error("launch_new_genome() in startup window", e)
179
-
180
- # Event handler for user clicking "Main Program" button - used to launch Main Window
181
- def launchMainWindow(self):
182
- try:
183
- # Make sure database directory variable is up-to-date based on what the user has in the text edit
184
- self.databaseDirectory = str(self.currentDirText.text())
185
-
186
- # Make sure the path is a valid path before launching New Genome
187
- if not os.path.isdir(self.databaseDirectory):
188
- show_message(
189
- fontSize=12,
190
- icon=QtWidgets.QMessageBox.Icon.Critical,
191
- title="Not a directory",
192
- message="The directory you selected does not exist.",
193
- )
194
- return
195
-
196
- # Check if database directory has CSPR files in it
197
- if not any(file.endswith(".cspr") for file in os.listdir(self.databaseDirectory)):
198
- show_message(
199
- fontSize=12,
200
- icon=QtWidgets.QMessageBox.Icon.Critical,
201
- title="Directory is invalid!",
202
- message="You must select a directory with CSPR Files!",
203
- )
204
- return
205
-
206
- # Change directory to database directory
207
- os.chdir(self.databaseDirectory)
208
-
209
- # Update database directory global variable
210
- GlobalSettings.CSPR_DB = self.databaseDirectory
211
-
212
- # Save database directory to CASPERinfo
213
- self.saveDatabaseDirectory()
214
-
215
- initialize_app_directories()
216
-
217
- # Fill in organism/endo/annotation dropdown information for main, mulit-targeting, and populatin analysis
218
- self.load_dropdown_data()
219
-
220
- # Show main window
221
- if GlobalSettings.mainWindow.first_show:
222
- GlobalSettings.mainWindow.first_show = False
223
- GlobalSettings.mainWindow.show()
224
- self.close()
225
-
226
- except Exception as e:
227
- show_error("launchMainWindow() in startup window", e)
228
-
229
- def load_dropdown_data(self):
230
- try:
231
- GlobalSettings.mainWindow.getData()
232
- GlobalSettings.mainWindow.fill_annotation_dropdown()
233
- logger.debug("Successfully loaded organism/endo/annotation drop down information in Main.")
234
- except Exception as e:
235
- show_error("load_dropdown_data() in Main", e)
236
-
237
- try:
238
- GlobalSettings.MTWin.launch()
239
- logger.debug("Successfully loaded organism/endo drop down information in Multi-targeting.")
240
- except Exception as e:
241
- show_error("load_dropdown_data() in Multi-targeting", e)
242
-
243
- try:
244
- GlobalSettings.pop_Analysis.launch()
245
- logger.debug("Successfully loaded organism/endo drop down information in Population Analysis.")
246
- except Exception as e:
247
- show_error("load_dropdown_data() in Population Analysis", e)
248
-
249
- def initialize_app_directories():
250
- required_dirs = ["FNA", "GBFF"]
251
- for directory in required_dirs:
252
- path = os.path.join(GlobalSettings.CSPR_DB, directory)
253
- if not os.path.exists(path):
254
- os.makedirs(path, exist_ok=True)
255
- logging.info(f"Directory created: {path}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/annotation_functions.py DELETED
@@ -1,47 +0,0 @@
1
- import Bio
2
-
3
- def check_key(key,dict):
4
- if key in dict.keys():
5
- return True
6
- else:
7
- return False
8
-
9
- def get_id(feature):
10
- if check_key('locus_tag',feature.qualifiers):
11
- return feature.qualifiers['locus_tag'][0]
12
- elif check_key('db_xref',feature.qualifiers):
13
- return feature.qualifiers['db_xref'][0]
14
- elif check_key('protein_id',feature.qualifiers):
15
- return feature.qualifiers['protein_id'][0]
16
- elif check_key('old_locus_tag',feature.qualifiers):
17
- return feature.qualifiers['old_locus_tag'][0]
18
- else:
19
- return "N/A"
20
-
21
- def get_name(feature):
22
- if check_key('gene',feature.qualifiers):
23
- return feature.qualifiers['gene'][0]
24
- elif check_key('gene_synonym',feature.qualifiers):
25
- return feature.qualifiers['gene_synonym'][0]
26
- elif check_key('product',feature.qualifiers):
27
- return feature.qualifiers['product'][0]
28
- else:
29
- return "N/A"
30
-
31
- def get_description(feature):
32
- if check_key('product',feature.qualifiers):
33
- return feature.qualifiers['product'][0]
34
- elif check_key('note',feature.qualifiers):
35
- return feature.qualifiers['note'][0]
36
- # elif check_key('gene',feature.qualifiers):
37
- # return feature.qualifiers['gene'][0]
38
- else:
39
- return "N/A"
40
-
41
- def get_strand(feature):
42
- if feature.location.strand == 1:
43
- return "+"
44
- elif feature.location.strand == -1:
45
- return "-"
46
- else:
47
- return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/closingWin.py DELETED
@@ -1,73 +0,0 @@
1
- import models.GlobalSettings as GlobalSettings
2
- import os
3
- from PyQt5 import QtWidgets, Qt, uic
4
- import traceback
5
- import math
6
- from utils.ui import show_error, scale_ui
7
-
8
- logger = GlobalSettings.logger
9
-
10
- ###########################################################
11
- # closingWindow: this class is a little window where the user can select which files they want to delete
12
- # Once they hit 'submit' it will delete all of the files selected, and close the program.
13
- # If no files are selected, the program closes and no files are deleted
14
- # Inputs are taking from the user (selecting files to delete and hitting submit), as well as GlobalSettings for the files in CSPR_DB
15
- # Outputs are the files are deleting, and the program is closed
16
- ###########################################################
17
- class closingWindow(QtWidgets.QMainWindow):
18
- def __init__(self):
19
- try:
20
- super(closingWindow, self).__init__()
21
- uic.loadUi(GlobalSettings.appdir + "ui/closing_window.ui", self)
22
- self.setWindowTitle("Delete Files")
23
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
24
-
25
- # Button
26
- self.submit_button.clicked.connect(self.submit_and_close)
27
-
28
- # Table
29
- self.files_table.setColumnCount(1)
30
- self.files_table.setShowGrid(True)
31
- self.files_table.setHorizontalHeaderLabels("File Name;".split(";"))
32
- self.files_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
33
- self.files_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
34
- self.files_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
35
-
36
-
37
- scale_ui(self, custom_scale_width=400, custom_scale_height=300)
38
-
39
-
40
- except Exception as e:
41
- show_error("Error initializing closingWindow class.", e)
42
-
43
- # this function will delete selected files, and then close the program
44
- def submit_and_close(self):
45
- try:
46
- # loop through the whole table
47
- for i in range(self.files_table.rowCount()):
48
- tabWidget = self.files_table.item(i, 0)
49
-
50
- # if that specific tab is selected, delete it. otherwise do nothing
51
- if tabWidget.isSelected():
52
- os.remove(tabWidget.text())
53
- self.close()
54
- except Exception as e:
55
- show_error("Error in sumbit_and_close() in closing window.", e)
56
-
57
- # this function gets all of the files from the CSPR_DB and puts them all into the table
58
- def get_files(self):
59
- try:
60
- loopCount = 0
61
- # get the file names from CSPR_DB
62
- files_names = os.listdir(GlobalSettings.CSPR_DB)
63
- files_names.sort(key=str.lower)
64
- self.files_table.setRowCount(len(files_names))
65
-
66
- # loop through and add them to the table
67
- for file in files_names:
68
- tabWidget = QtWidgets.QTableWidgetItem(file)
69
- self.files_table.setItem(loopCount, 0, tabWidget)
70
- loopCount += 1
71
- self.files_table.resizeColumnsToContents()
72
- except Exception as e:
73
- show_error("Error in get_files() in closing window.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/export_tool.py DELETED
@@ -1,259 +0,0 @@
1
- import models.GlobalSettings as GlobalSettings
2
- from utils.Algorithms import get_table_headers
3
- import os
4
- from PyQt5 import QtWidgets, Qt, uic, QtCore, QtGui
5
- import platform
6
- import traceback
7
- import math
8
- from utils.ui import show_message, show_error, scale_ui, center_ui
9
-
10
- logger = GlobalSettings.logger
11
-
12
- # This class opens a window for the user to select where they want the CSV file exported to, and the name of the file
13
- # It takes the highlighted data from the Results page, and creates a CSV file from that
14
- class export_tool(QtWidgets.QMainWindow):
15
- def __init__(self):
16
- try:
17
- super(export_tool, self).__init__()
18
- uic.loadUi(GlobalSettings.appdir + 'ui/export_tool.ui', self)
19
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + "cas9image.ico"))
20
-
21
- self.browse_button.clicked.connect(self.browseForFolder)
22
- self.cancel_button.clicked.connect(self.cancel_function)
23
- self.export_button.clicked.connect(self.export_function)
24
-
25
- # Set up validators for input fields:
26
- reg_ex = QtCore.QRegExp("[^,]+") # No commas
27
- input_validator = QtGui.QRegExpValidator(reg_ex, self)
28
- self.leading_seq.setValidator(input_validator)
29
- self.trailing_seq.setValidator(input_validator)
30
-
31
- # GroupBox styling
32
- groupbox_style = """
33
- QGroupBox:title{subcontrol-origin: margin;
34
- left: 10px;
35
- padding: 0 5px 0 5px;}
36
- QGroupBox#gRNA_Options{border: 2px solid rgb(111,181,110);
37
- border-radius: 9px;
38
- margin-top: 10px;
39
- font: bold 14pt 'Arial';} """
40
- self.gRNA_Options.setStyleSheet(groupbox_style)
41
-
42
- self.location = self.fileLocation_line_edit.text()
43
- self.selected_table_items = []
44
- self.window = ""
45
- self.num_columns = []
46
- self.locus_tag = False
47
- self.gene_name = False
48
-
49
- self.setWindowTitle("Export to CSV")
50
- scale_ui(self, custom_scale_width=650, custom_scale_height=200)
51
-
52
- except Exception as e:
53
- show_error("Error initializing export_tool class.", e)
54
-
55
- # launch function. Called in Results.
56
- # parameter expect: a list of the items selected from the window.
57
- def launch(self, select_items, window):
58
- try:
59
- if platform.system() == "Windows":
60
- self.fileLocation_line_edit.setText(GlobalSettings.CSPR_DB + "\\")
61
- else:
62
- self.fileLocation_line_edit.setText(GlobalSettings.CSPR_DB + "/")
63
- self.selected_table_items = select_items
64
- self.window = window
65
- center_ui(self)
66
- self.show()
67
- self.activateWindow()
68
- except Exception as e:
69
- show_error("Error in launch() in export_tool.", e)
70
-
71
- # Takes the path and file name and combines them
72
- # Writes the header line, as well as ever line selected to that file
73
- # calls the cancel function when it's done
74
- def export_function(self):
75
- try:
76
- delim = self.delimBox.currentText()
77
- # get the full path ( path and file name)
78
- file_name = self.filename_line_edit.text()
79
- if file_name == "":
80
- file_name = "exported_gRNAs"
81
- self.location = self.fileLocation_line_edit.text()
82
- full_path = ""
83
- if '.' in file_name: # If user added the file extension...
84
- full_path = self.location + file_name
85
- else:
86
- if delim == ",":
87
- full_path = self.location + file_name + '.csv'
88
- elif delim == r"\t":
89
- delim = "\t"
90
- full_path = self.location + file_name + '.tsv'
91
- else:
92
- full_path = self.location + file_name + '.txt'
93
- try:
94
- output_data = open(full_path, 'w')
95
- """ Write the table headers """
96
- if self.window == "mt": ###Change headers for multitargeting table export
97
- headers = get_table_headers(GlobalSettings.MTWin.table)
98
- num_cols = len(headers) # Calculate the number of columns based on the headers list above
99
- insertion_index = headers.index("% Consensus")
100
- headers.insert(insertion_index, "Full Sequence")
101
- output_data.write(delim.join(headers)+"\n")
102
- elif self.window == "pa":
103
- headers = get_table_headers(GlobalSettings.pop_Analysis.table2)
104
- num_cols = len(headers) # Calculate the number of columns based on the headers list above
105
- insertion_index = headers.index("% Consensus")
106
- headers.insert(insertion_index, "Full Sequence")
107
- output_data.write(delim.join(headers)+"\n")
108
- else: ###Change headers for view results export
109
- headers = get_table_headers(GlobalSettings.mainWindow.Results.targetTable)
110
- headers.remove("Details") # For some reason, the details column doesn't carry any "items"
111
- num_cols = len(headers) # Calculate the number of columns based on the headers list above
112
- insertion_index = headers.index("Strand")
113
- headers.insert(insertion_index, "Full Sequence")
114
-
115
- if GlobalSettings.mainWindow.radioButton_Gene.isChecked(): # If the user chose to search via Feature
116
- tmp = GlobalSettings.mainWindow.Results.comboBoxGene.currentText().split(":") # Check to see if the locus tag was found for the current gene
117
- if len(tmp) > 1: # If locus tag exists for gene, include in output
118
- headers.extend(["Locus_Tag","Gene_Name"])
119
- output_data.write(delim.join(headers)+"\n")
120
- self.locus_tag = True
121
- self.gene_name = True
122
- else: # If locus tag does not exist for gene, only include the gene name
123
- headers.append("Gene_Name")
124
- output_data.write(delim.join(headers)+"\n")
125
- self.gene_name = True
126
- self.locus_tag = False
127
- else: # If user searched by sequence or position, don't include locus tag or gene name
128
- output_data.write(delim.join(headers)+"\n")
129
- self.gene_name = False
130
- self.locus_tag = False
131
-
132
- """ Write the data out """
133
- tmp_list = []
134
- if self.locus_tag: #If the user is exporting data from VT and locus tag exists for current gene
135
- tmp = GlobalSettings.mainWindow.Results.comboBoxGene.currentText().split(":") # Get the locus tag
136
- locus_tag = str(tmp[0].strip())
137
- gene_name = str(tmp[-1].strip())
138
- seq_index = headers.index("Sequence") # Get the gene name
139
- it = 0
140
- for i, item in enumerate(self.selected_table_items): # Loop through all the items in the View Targets table
141
- if (i+1) % num_cols == 0:
142
- tmp_list.append(item.text())
143
- tmp_list.append(locus_tag)
144
- tmp_list.append(gene_name)
145
- output_data.write(delim.join(tmp_list)+"\n") # Write data out
146
- tmp_list.clear() # Reset list
147
- it = 0 # Reset iterator
148
- elif it == seq_index:
149
- tmp_list.append(item.text())
150
- tmp_list.append(self.leading_seq.text().strip() + item.text() + self.trailing_seq.text().strip()) #5' Leader + gRNA + 3' Trailer
151
- it += 1
152
- else:
153
- tmp_list.append(item.text())
154
- it += 1
155
- elif self.gene_name: #If the user is exporting data from VT and locus tag doesn't exist for current gene
156
- gene_name = str(GlobalSettings.mainWindow.Results.comboBoxGene.currentText().strip()) # Get the locus tag
157
- seq_index = headers.index("Sequence") # Get the gene name
158
- it = 0
159
- for i, item in enumerate(self.selected_table_items): # Loop through all the items in the View Targets table
160
- if (i+1) % num_cols == 0:
161
- tmp_list.append(item.text())
162
- tmp_list.append(gene_name)
163
- output_data.write(delim.join(tmp_list)+"\n")
164
- tmp_list.clear()
165
- it = 0 # Reset iterator
166
- elif it == seq_index:
167
- tmp_list.append(item.text())
168
- tmp_list.append(self.leading_seq.text().strip() + item.text() + self.trailing_seq.text().strip()) #5' Leader + gRNA + 3' Trailer
169
- it += 1
170
- else:
171
- tmp_list.append(item.text())
172
- it += 1
173
- elif self.window in ["mt", "pa"]: #If the user is exporting data from multitargeting
174
- seq_index = headers.index("Consensus Sequence")
175
- it = 0
176
- for i, item in enumerate(self.selected_table_items): # Loop through all the items in the View Targets table
177
- if (i+1) % num_cols == 0:
178
- tmp_list.append(item.text())
179
- output_data.write(str(delim.join(tmp_list))+"\n")
180
- tmp_list.clear()
181
- it = 0 # Reset iterator
182
- elif it == seq_index:
183
- tmp_list.append(item.text())
184
- tmp_list.append(self.leading_seq.text().strip() + item.text() + self.trailing_seq.text().strip()) #5' Leader + gRNA + 3' Trailer
185
- it += 1
186
- else:
187
- tmp_list.append(item.text())
188
- it += 1
189
- else: #If the user is exporting data from View Targets but is not using Feature search
190
- seq_index = headers.index("Sequence") # Get the gene name
191
- it = 0
192
- for i, item in enumerate(self.selected_table_items): # Loop through all the items in the View Targets table
193
- if (i+1) % num_cols == 0:
194
- tmp_list.append(item.text())
195
- output_data.write(delim.join(tmp_list)+"\n")
196
- tmp_list.clear()
197
- it = 0 # Reset iterator
198
- elif it == seq_index:
199
- tmp_list.append(item.text())
200
- tmp_list.append(self.leading_seq.text().strip() + item.text() + self.trailing_seq.text().strip()) #5' Leader + gRNA + 3' Trailer
201
- it += 1
202
- else:
203
- tmp_list.append(item.text())
204
- it += 1
205
- output_data.close()
206
- except PermissionError:
207
- show_error("This file cannot be opened. Please make sure that the file is not opened elsewhere and try again.", e)
208
- return
209
-
210
- except Exception as e:
211
- show_error("Error in export_function() in export_tool.", e)
212
- return
213
-
214
- """ Print "finished" message """
215
- show_message(
216
- fontSize=12,
217
- icon=QtWidgets.QMessageBox.Icon.Information,
218
- title="Export Complete",
219
- message=f"Export to {full_path} was successful."
220
- )
221
-
222
- # close the window
223
- self.cancel_function()
224
- except Exception as e:
225
- show_error("Error in export_function() in export_tool.", e)
226
-
227
- # Resets everything to the init funciton
228
- # then closes the window
229
- def cancel_function(self):
230
- try:
231
- if platform.system() == "Windows":
232
- self.fileLocation_line_edit.setText(GlobalSettings.CSPR_DB + "\\")
233
- else:
234
- self.fileLocation_line_edit.setText(GlobalSettings.CSPR_DB + "/")
235
- self.filename_line_edit.setText("")
236
- self.location = ""
237
- self.hide()
238
- except Exception as e:
239
- show_error("Error in cancel_function() in export_tool.", e)
240
-
241
- # browse for folder function
242
- # allows user to browse for a folder where to store the CSV file
243
- def browseForFolder(self):
244
- try:
245
- # get the folder
246
- filed = QtWidgets.QFileDialog()
247
- mydir = QtWidgets.QFileDialog.getExistingDirectory(filed, "Open a Folder",
248
- GlobalSettings.CSPR_DB, QtWidgets.QFileDialog.ShowDirsOnly)
249
- if(os.path.isdir(mydir) == False):
250
- return
251
-
252
- if platform.system() == "Windows":
253
- self.fileLocation_line_edit.setText(mydir + "\\")
254
- self.location = mydir + "\\"
255
- else:
256
- self.fileLocation_line_edit.setText(mydir + "/")
257
- self.location = mydir + "/"
258
- except Exception as e:
259
- show_error("Error in browseForFolder() in export_tool.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/generateLib.py DELETED
@@ -1,662 +0,0 @@
1
- import models.GlobalSettings as GlobalSettings
2
- import os
3
- from PyQt5 import QtWidgets, Qt, uic, QtCore
4
- from functools import partial
5
- from models.CSPRparser import CSPRparser
6
- import re
7
- import platform
8
- import traceback
9
- import math
10
- from utils.ui import show_message, show_error, scale_ui, center_ui
11
- from views.annotation_functions import *
12
-
13
- logger = GlobalSettings.logger
14
-
15
- # this class is a window that allows the user to select the settings for Generate Library
16
- # When the user clicks Generate Library, it goes ahead and gets the Annotation Data needed
17
- # Then the user can select the settings they want, and then hit submit.
18
- # It creates a txt file with the data
19
- class genLibrary(QtWidgets.QMainWindow):
20
- def __init__(self):
21
- try:
22
- super(genLibrary, self).__init__()
23
- uic.loadUi(GlobalSettings.appdir + 'ui/generate_library.ui', self)
24
- self.setWindowTitle('Generate Library')
25
- self.setWindowIcon(Qt.QIcon(GlobalSettings.appdir + 'cas9image.ico'))
26
-
27
- groupbox_style = """
28
- QGroupBox:title{subcontrol-origin: margin;
29
- left: 10px;
30
- padding: 0 5px 0 5px;}
31
- QGroupBox#Step1{border: 2px solid rgb(111,181,110);
32
- border-radius: 9px;
33
- font: bold 14pt 'Arial';
34
- margin-top: 10px;}"""
35
- self.Step1.setStyleSheet(groupbox_style)
36
- self.Step2.setStyleSheet(groupbox_style.replace("Step1", "Step2"))
37
- self.Step3.setStyleSheet(groupbox_style.replace("Step1", "Step3"))
38
- self.Step4.setStyleSheet(groupbox_style.replace("Step1", "Step4"))
39
-
40
- self.cancel_button.clicked.connect(self.cancel_function)
41
- self.BrowseButton.clicked.connect(self.browse_function)
42
- self.submit_button.clicked.connect(self.submit_data)
43
- self.progressBar.setValue(0)
44
-
45
- self.anno_data = dict()
46
- self.kegg_nonKegg = ''
47
- self.gen_lib_dict = dict()
48
- self.cspr_data = dict()
49
- self.Output = dict()
50
- self.off_tol = .05
51
- self.off_max_misMatch = 4
52
- self.off_target_running = False
53
- self.parser = CSPRparser("")
54
-
55
- # set the numbers for the num genes combo box item
56
- for i in range(10):
57
- self.numGenescomboBox.addItem(str(i + 1))
58
-
59
- # set the numbers for the minOn combo box
60
- for i in range(19, 70):
61
- self.minON_comboBox.addItem(str(i + 1))
62
-
63
- scale_ui(self, custom_scale_width=950, custom_scale_height=500)
64
-
65
- except Exception as e:
66
- show_error("Error initializing generate library class.", e)
67
-
68
- # this function launches the window
69
- # Parameters:
70
- # annotation_data: a dictionary that has the data for the annotations searched for
71
- # currently MainWindow's searches dict is passed into this
72
- # org_file: the cspr_file that pertains to the organism that user is using at the time
73
- # anno_type: whether the user is using KEGG or another type of annotation file
74
- def launch(self, annotation_data, org_file, anno_type):
75
- try:
76
- self.cspr_file = org_file
77
- self.db_file = org_file[:org_file.find('.')] + '_repeats.db'
78
- self.anno_data = annotation_data
79
- self.kegg_nonKegg = anno_type
80
- self.process = QtCore.QProcess()
81
- self.parser.fileName = org_file
82
-
83
- # setting the path and file name fields
84
- index1 = self.cspr_file.find('.')
85
- if platform.system() == "Windows":
86
- index2 = self.cspr_file.rfind('\\')
87
- else:
88
- index2 = self.cspr_file.rfind('/')
89
-
90
- self.filename_input.setText(self.cspr_file[index2 + 1:index1] + '_lib')
91
-
92
-
93
- if platform.system() == "Windows":
94
- self.output_path.setText(GlobalSettings.CSPR_DB + "\\")
95
- else:
96
- self.output_path.setText(GlobalSettings.CSPR_DB + "/")
97
-
98
- # depending on the type of file, build the dictionary accordingly
99
- self.build_dict_non_kegg()
100
-
101
- # get the gRNA data from the cspr file
102
- self.cspr_data = self.parser.gen_lib_parser(self.gen_lib_dict, GlobalSettings.mainWindow.endoChoice.currentText())
103
- self.get_endo_data()
104
-
105
- center_ui(self)
106
- self.show()
107
- self.activateWindow()
108
- except Exception as e:
109
- show_error("Error in launch() in generate library.", e)
110
-
111
- def get_endo_data(self):
112
- try:
113
- f = open(GlobalSettings.appdir + "CASPERinfo")
114
- self.endo_data = {}
115
- while True:
116
- line = f.readline()
117
- if line.startswith('ENDONUCLEASES'):
118
- while True:
119
- line = f.readline()
120
- line = line.replace("\n","")
121
- if (line[0] == "-"):
122
- break
123
- line_tokened = line.split(";")
124
- if len(line_tokened) == 10:
125
- endo = line_tokened[0]
126
- five_length = line_tokened[2]
127
- seed_length = line_tokened[3]
128
- three_length = line_tokened[4]
129
- prime = line_tokened[5]
130
- hsu = line_tokened[9]
131
- self.endo_data[endo] = [int(five_length) + int(three_length) + int(seed_length), prime, "MATRIX:" + hsu]
132
-
133
- break
134
- f.close()
135
- except Exception as e:
136
- show_error("Error in get_endo_data() in generate library.", e)
137
-
138
- # this is here in case the user clicks 'x' instead of cancel. Just calls the cancel function
139
- def closeEvent(self, event):
140
- try:
141
- closeWindow = self.cancel_function()
142
-
143
- # if the user is doing OT and does not decide to cancel it ignore the event
144
- if closeWindow == -2:
145
- event.ignore()
146
- else:
147
- event.accept()
148
- except Exception as e:
149
- show_error("Error in closeEvent() in generate library.", e)
150
-
151
- # this function takes all of the cspr data and compresses it again for off-target usage
152
- def compress_file_off(self):
153
- try:
154
- if platform.system() == "Windows":
155
- file = GlobalSettings.CSPR_DB + "\\off_input.txt"
156
- else:
157
- file = GlobalSettings.CSPR_DB + "/off_input.txt"
158
- f = open(file, 'w')
159
- for gene in self.cspr_data:
160
- for j in range(len(self.cspr_data[gene])):
161
- loc = self.cspr_data[gene][j][0]
162
- seq = self.cspr_data[gene][j][1]
163
- pam = self.cspr_data[gene][j][2]
164
- score = self.cspr_data[gene][j][3]
165
- strand = self.cspr_data[gene][j][4]
166
- output = str(loc) + ';' + str(seq) + ';' + str(pam) + ';' + str(score) + ';' + str(strand)
167
- f.write(output + '\n')
168
- f.close()
169
- except Exception as e:
170
- show_error("Error in compress_file_off() in generate library.", e)
171
-
172
- # this function parses the temp_off file, which holds the off-target analysis results
173
- # it also updates each target in the cspr_data dictionary to replace the endo with the target's results in off-target
174
- def parse_off_file(self):
175
- try:
176
- if platform.system() == "Windows":
177
- file = GlobalSettings.CSPR_DB + "\\temp_off.txt"
178
- else:
179
- file = GlobalSettings.CSPR_DB + "/temp_off.txt"
180
- f = open(file, "r")
181
- file_data = f.read().split('\n')
182
- f.close()
183
- scoreDict = dict()
184
-
185
- # get the data from the file
186
- for i in range(len(file_data)):
187
- if file_data[i] == 'AVG OUTPUT':
188
- continue
189
- elif file_data[i] != '':
190
- buffer = file_data[i].split(':')
191
- scoreDict[buffer[0]] = buffer[1]
192
-
193
- # update cspr_Data
194
- for gene in self.cspr_data:
195
- for i in range(len(self.cspr_data[gene])):
196
- tempTuple = (self.cspr_data[gene][i][0], self.cspr_data[gene][i][1], self.cspr_data[gene][i][2], self.cspr_data[gene][i][3], self.cspr_data[gene][i][4], scoreDict[self.cspr_data[gene][i][1]])
197
- self.cspr_data[gene][i] = tempTuple
198
- except Exception as e:
199
- show_error("Error in parse_off_file() in generate library.", e)
200
-
201
- # this function runs the off_target command
202
- # NOTE: some changes may be needed to get it to work with other OS besides windows
203
- def get_offTarget_data(self, num_targets, minScore, spaceValue, output_file, fiveseq):
204
- try:
205
- self.perc = False
206
- self.bool_temp = False
207
- self.running = False
208
-
209
- # when finished, parse the off file, and then generate the lib
210
- def finished():
211
- if self.off_target_running:
212
- self.progressBar.setValue(100)
213
- self.parse_off_file()
214
- did_work = self.generate(num_targets, minScore, spaceValue, output_file, fiveseq)
215
- self.off_target_running = False
216
- #self.process.kill()
217
- if did_work != -1:
218
- self.cancel_function()
219
- show_message(
220
- fontSize=12,
221
- icon=QtWidgets.QMessageBox.Icon.Information,
222
- title="Library Generated!",
223
- message="CASPER has finished generating your library!"
224
- )
225
- os.remove(GlobalSettings.CSPR_DB + '/off_input.txt')
226
- os.remove(GlobalSettings.CSPR_DB + '/temp_off.txt')
227
-
228
- # as off-targeting outputs things, update the off-target progress bar
229
- def progUpdate(p):
230
- line = str(self.process.readAllStandardOutput())
231
- line = line[2:]
232
- line = line[:len(line) - 1]
233
- if platform.system() == 'Windows':
234
- for lines in filter(None, line.split(r'\r\n')):
235
- if (lines.find("Running Off Target Algorithm for") != -1 and self.perc == False):
236
- self.perc = True
237
- if (self.perc == True and self.bool_temp == False and lines.find(
238
- "Running Off Target Algorithm for") == -1):
239
- lines = lines[32:]
240
- lines = lines.replace("%", "")
241
- if (float(lines) <= 99.5):
242
- num = float(lines)
243
- self.progressBar.setValue(num)
244
- else:
245
- self.bool_temp = True
246
- else:
247
- for lines in filter(None, line.split(r'\n')):
248
- if (lines.find("Running Off Target Algorithm for") != -1 and self.perc == False):
249
- self.perc = True
250
- if (self.perc == True and self.bool_temp == False and lines.find(
251
- "Running Off Target Algorithm for") == -1):
252
- lines = lines[32:]
253
- lines = lines.replace("%", "")
254
- if (float(lines) <= 99.5):
255
- num = float(lines)
256
- self.progressBar.setValue(num)
257
- else:
258
- self.bool_temp = True
259
-
260
- if platform.system() == 'Windows':
261
- app_path = GlobalSettings.appdir
262
- exe_path = app_path + 'OffTargetFolder\\OT_Win.exe'
263
- output_path = '"' + GlobalSettings.CSPR_DB + '\\temp_off.txt" '
264
- data_path = '"' + GlobalSettings.CSPR_DB + "\\off_input.txt" + '" '
265
- elif platform.system() == 'Linux':
266
- app_path = GlobalSettings.appdir.replace('\\', '/')
267
- exe_path = app_path + r'OffTargetFolder/OT_Lin'
268
- output_path = '"' + GlobalSettings.CSPR_DB + '/temp_off.txt" '
269
- data_path = '"' + GlobalSettings.CSPR_DB + "/off_input.txt" + '" '
270
- else:
271
- app_path = GlobalSettings.appdir.replace('\\', '/')
272
- exe_path = app_path + r'OffTargetFolder/OT_Mac'
273
- output_path = '"' + GlobalSettings.CSPR_DB + '/temp_off.txt" '
274
- data_path = '"' + GlobalSettings.CSPR_DB + "/off_input.txt" + '" '
275
- exe_path = '"' + exe_path + '" '
276
- cspr_path = '"' + self.cspr_file + '" '
277
- db_path = '"' + self.db_file + '" '
278
- filename = output_path
279
- filename = filename[:len(filename) - 1]
280
- filename = filename[1:]
281
- filename = filename.replace('"', '')
282
- CASPER_info_path = '"' + app_path + 'CASPERinfo' +'" '
283
- num_of_mismathes = self.off_max_misMatch
284
- tolerance = self.off_tol # create command string
285
- endo = '"' + GlobalSettings.mainWindow.endoChoice.currentText() + '" '
286
- detailed_output = " False "
287
- avg_output = "True"
288
- hsu = ' "' + self.endo_data[GlobalSettings.mainWindow.endoChoice.currentText()][2] + '"'
289
-
290
- # set the off_target_running to true, to keep the user from closing the window while it is running
291
- self.off_target_running = True
292
-
293
- cmd = exe_path + data_path + endo + cspr_path + db_path + output_path + CASPER_info_path + str(
294
- num_of_mismathes) + ' ' + str(tolerance) + detailed_output + avg_output + hsu
295
-
296
- if platform.system() == 'Windows':
297
- cmd = cmd.replace('/', '\\')
298
- self.process.readyReadStandardOutput.connect(partial(progUpdate, self.process))
299
- self.process.readyReadStandardError.connect(partial(progUpdate, self.process))
300
- self.progressBar.setValue(0)
301
- QtCore.QTimer.singleShot(100, partial(self.process.start, cmd))
302
- self.process.finished.connect(finished)
303
- except Exception as e:
304
- show_error("Error in get_offTarget_data() in generate library.", e)
305
-
306
- # submit function
307
- # this function takes all of the input from the window, and calls the generate function
308
- # Still need to add the checks for 5' seq, and the percentage thing
309
- def submit_data(self):
310
- try:
311
- if self.off_target_running:
312
- return
313
- output_file = self.output_path.text() + self.filename_input.text()
314
-
315
- minScore = int(self.minON_comboBox.currentText())
316
- num_targets = int(self.numGenescomboBox.currentText())
317
- fiveseq = ''
318
-
319
- # error check for csv files
320
- if output_file.endswith('.txt'):
321
- output_file = output_file.replace('.txt', '.csv')
322
- elif not output_file.endswith('.txt') and not output_file.endswith('.csv'):
323
- output_file = output_file + '.csv'
324
-
325
- # error checking for the space value
326
- # if they enter nothing, default to 15 and also make sure it's actually a digit
327
- if self.space_line_edit.text() == '':
328
- spaceValue = 15
329
- elif self.space_line_edit.text().isdigit():
330
- spaceValue = int(self.space_line_edit.text())
331
- elif not self.space_line_edit.text().isdigit():
332
- show_message(
333
- fontSize=12,
334
- icon=QtWidgets.QMessageBox.Icon.Critical,
335
- title="Error",
336
- message="Please enter integers only for space between guides."
337
- )
338
- return
339
- # if space value is more than 200, default to 200
340
- if spaceValue > 200:
341
- spaceValue = 200
342
- elif spaceValue < 0:
343
- show_message(
344
- fontSize=12,
345
- icon=QtWidgets.QMessageBox.Icon.Critical,
346
- title="Error",
347
- message="Please enter a space-value that is 0 or greater."
348
- )
349
- return
350
-
351
- if self.find_off_Checkbox.isChecked():
352
- self.compress_file_off()
353
-
354
- # get the fiveprimseq data and error check it
355
- if self.fiveprimeseq.text() != '' and self.fiveprimeseq.text().isalpha():
356
- fiveseq = self.fiveprimeseq.text()
357
- elif self.fiveprimeseq.text() != '' and not self.fiveprimeseq.text().isalpha():
358
- show_message(
359
- fontSize=12,
360
- icon=QtWidgets.QMessageBox.Icon.Critical,
361
- title="Error",
362
- message="Please make sure only the letters A, T, G, or C are added into 5' End specificity box."
363
- )
364
- return
365
-
366
- # get the targeting range data, and error check it here
367
- if not self.start_target_range.text().isdigit() or not self.end_target_range.text().isdigit():
368
- show_message(
369
- fontSize=12,
370
- icon=QtWidgets.QMessageBox.Icon.Critical,
371
- title="Error",
372
- message="Error: Please make sure that the start and end target ranges are numbers only. Please make sure that start is 0 or greater, and end is 100 or less. "
373
- )
374
- return
375
- elif int(self.start_target_range.text()) >= int(self.end_target_range.text()):
376
- show_message(
377
- fontSize=12,
378
- icon=QtWidgets.QMessageBox.Icon.Critical,
379
- title="Error",
380
- message="Please make sure that the start number is always less than the end number"
381
- )
382
- return
383
-
384
- # if they check Off-Targeting
385
- if self.find_off_Checkbox.isChecked():
386
- # make sure its a digit
387
- if self.maxOFF_comboBox.text() == '' or not self.maxOFF_comboBox.text().isdigit() and '.' not in self.maxOFF_comboBox.text():
388
- show_message(
389
- fontSize=12,
390
- icon=QtWidgets.QMessageBox.Icon.Critical,
391
- title="Error",
392
- message="Please enter only numbers for Maximum Off-Target Score. It cannot be left blank"
393
- )
394
- return
395
- else:
396
- # make sure it between 0 and .5
397
- if not 0.0 < float(self.maxOFF_comboBox.text()) <= .5:
398
- show_message(
399
- fontSize=12,
400
- icon=QtWidgets.QMessageBox.Icon.Critical,
401
- title="Error",
402
- message="Please enter a max off-target score between 0 and 0.5!"
403
- )
404
- return
405
- # compress the data, and then run off-targeting
406
- self.compress_file_off()
407
- self.get_offTarget_data(num_targets, minScore, spaceValue, output_file, fiveseq)
408
- else:
409
- # actually call the generate function
410
- did_work = self.generate(num_targets, minScore, spaceValue, output_file, fiveseq)
411
-
412
- if did_work != -1:
413
- self.cancel_function()
414
- show_message(
415
- fontSize=12,
416
- icon=QtWidgets.QMessageBox.Icon.Critical,
417
- title="Library Generated!",
418
- message="CASPER has finished generating your library!"
419
- )
420
- except Exception as e:
421
- show_error("Error in submit_data() in generate library.", e)
422
-
423
- # clears everything and hides the window
424
- def cancel_function(self):
425
- try:
426
- if self.off_target_running:
427
- msgBox = QtWidgets.QMessageBox()
428
- msgBox.setStyleSheet("font: " + str(12) + "pt 'Arial'")
429
- msgBox.setIcon(QtWidgets.QMessageBox.Icon.Question)
430
- msgBox.setWindowTitle("Off-Targeting is running")
431
- msgBox.setText(
432
- "Off-Targetting is running. Closing this window will cancel that process, and return to the main window. .\n Do you wish to continue?")
433
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.Yes)
434
- msgBox.addButton(QtWidgets.QMessageBox.StandardButton.No)
435
- msgBox.exec()
436
-
437
- if (msgBox.result() == QtWidgets.QMessageBox.No):
438
- return -2
439
- else:
440
- self.off_target_running = False
441
- self.process.kill()
442
-
443
- self.cspr_file = ''
444
- self.anno_data = list()
445
-
446
- self.filename_input.setText('')
447
- self.output_path.setText('')
448
-
449
- self.gen_lib_dict.clear()
450
- self.cspr_data.clear()
451
- self.Output.clear()
452
-
453
- self.start_target_range.setText('0')
454
- self.end_target_range.setText('100')
455
- self.space_line_edit.setText('15')
456
- self.find_off_Checkbox.setChecked(False)
457
- self.modifyParamscheckBox.setChecked(False)
458
- self.maxOFF_comboBox.setText('')
459
- self.fiveprimeseq.setText('')
460
- self.off_target_running = False
461
- self.progressBar.setValue(0)
462
-
463
- self.hide()
464
- except Exception as e:
465
- show_error("Error in cancel_function() in generate library.", e)
466
-
467
- # allows the user to browse for a folder
468
- # stores their selection in the output_path line edit
469
- def browse_function(self):
470
- try:
471
- if self.off_target_running:
472
- return
473
- # get the folder
474
- filed = QtWidgets.QFileDialog()
475
- mydir = QtWidgets.QFileDialog.getExistingDirectory(filed, "Open a Folder",
476
- GlobalSettings.CSPR_DB, QtWidgets.QFileDialog.ShowDirsOnly)
477
- if(os.path.isdir(mydir) == False):
478
- return
479
-
480
- # make sure to append the '/' to the folder path
481
- if platform.system() == "Windwos":
482
- self.output_path.setText(mydir + "\\")
483
- else:
484
- self.output_path.setText(mydir + "/")
485
- except Exception as e:
486
- show_error("Error in browse_function() in generate library.", e)
487
-
488
- # this function builds the dictionary that is used in the generate function
489
- # this is the version that builds it from data from feature_table, gbff, or gff
490
- # builds it exactly as Brian built it in the files given
491
- def build_dict_non_kegg(self):
492
- try:
493
- for tuple in self.anno_data:
494
- chrom = tuple[0]
495
- feature = tuple[1]
496
- feature_id = get_id(feature)
497
- feature_name = get_name(feature)
498
- feature_desc = get_description(feature)
499
- ### Order: chromosome number, gene start, gene end, dir of gene, gene description, gene name/locus tag
500
- self.gen_lib_dict[feature_name] = [chrom,int(feature.location.start),int(feature.location.end),get_strand(feature),get_description(feature),get_name(feature)]
501
- except Exception as e:
502
- show_error("Error in build_dict_non_kegg() in generate library.", e)
503
-
504
- # generate function taken from Brian's code
505
- def generate(self,num_targets_per_gene, score_limit, space, output_file, fiveseq):
506
- try:
507
- deletedDict = dict()
508
-
509
- # check and see if we need to search based on target_range
510
- startNum = float(self.start_target_range.text())
511
- endNum = float(self.end_target_range.text())
512
- checkStartandEndBool = False
513
- if startNum != 0.0 or endNum != 100.0:
514
- if startNum >= 0.0 and endNum <= 100.0:
515
- startNum = startNum / 100
516
- endNum = endNum / 100
517
- checkStartandEndBool = True
518
- else:
519
- show_message(
520
- fontSize=12,
521
- icon=QtWidgets.QMessageBox.Icon.Critical,
522
- title="Invalid Targeting Range:",
523
- message="Please select a targeting range between 0 and 100."
524
- )
525
- return -1
526
-
527
- for gene in self.gen_lib_dict:
528
- target_list = self.cspr_data[gene] # Gets the gRNAs for given gene
529
-
530
- #target_list = chrom_list[k:l+1]
531
- # Reverse the target list if the gene is on negative strand:
532
- if self.gen_lib_dict[gene][3] == "-":
533
- target_list.reverse()
534
-
535
- # Filter out the guides with low scores and long strings of T's
536
- # also store the ones deleted if the user selects 'modify search parameters'
537
- if self.modifyParamscheckBox.isChecked():
538
- deletedDict[gene] = list()
539
- for i in range(len(target_list) - 1, -1, -1): ### Start at end and move backwards through list
540
- # check the target_range here
541
- if int(target_list[i][3]) < int(score_limit):
542
- if self.modifyParamscheckBox.isChecked():
543
- deletedDict[gene].append(target_list[i])
544
- target_list.pop(i)
545
- # check for gRNAs with poly T regions here
546
- elif re.search("T{5,10}", target_list[i][1]) is not None:
547
- if self.modifyParamscheckBox.isChecked():
548
- deletedDict[gene].append(target_list[i])
549
- target_list.pop(i)
550
-
551
- # check for the fiveseq
552
- if fiveseq != '':
553
- for i in range(len(target_list) - 1, -1, -1): ### Start at end and move backwards through list
554
- if not target_list[i][1].startswith(fiveseq.upper()):
555
- if self.modifyParamscheckBox.isChecked():
556
- deletedDict[gene].append(target_list[i])
557
- target_list.pop(i)
558
- # check the target range here
559
- if checkStartandEndBool:
560
- for i in range(len(target_list) - 1, -1, -1):
561
- totalDistance = self.gen_lib_dict[gene][2] - self.gen_lib_dict[gene][1]
562
- target_loc = abs(int(target_list[i][0])) - int(self.gen_lib_dict[gene][1])
563
- myRatio = target_loc / totalDistance
564
-
565
- if not (startNum <= myRatio <= endNum):
566
- if self.modifyParamscheckBox.isChecked():
567
- deletedDict[gene].append(target_list[i])
568
- target_list.pop(i)
569
- # if the user selected off-targeting, check to see that the targets do not exceed the selected max score
570
- if self.find_off_Checkbox.isChecked():
571
- maxScore = float(self.maxOFF_comboBox.text())
572
- for i in range(len(target_list) - 1, -1, -1):
573
- if maxScore < float(target_list[i][5]):
574
- if self.modifyParamscheckBox.isChecked():
575
- deletedDict[gene].append(target_list[i])
576
- target_list.pop(i)
577
- # Now generating the targets
578
- self.Output[gene] = list()
579
- i = 0
580
- vec_index = 0
581
- prev_target = (0, "xyz", 'abc', 1, "-")
582
- while i < num_targets_per_gene:
583
- # select the first five targets with the score and space filter that is set in the beginning
584
- if len(target_list) == 0 or vec_index >= len(target_list):
585
- break
586
- while abs(int(target_list[vec_index][0]) - int(prev_target[0])) < int(space):
587
- if target_list[vec_index][3] > prev_target[3] and prev_target != (0,"xyz", "abc", 1, "-"):
588
- self.Output[gene].remove(prev_target)
589
- self.Output[gene].append(target_list[vec_index])
590
- prev_target = target_list[vec_index]
591
- vec_index += 1
592
- # check and see if there will be a indexing error
593
- if vec_index >= len(target_list) - 1:
594
- vec_index = vec_index - 1
595
- break
596
- # Add the new target to the output and add another to i
597
- self.Output[gene].append(target_list[vec_index])
598
- prev_target = target_list[vec_index]
599
- i += 1
600
- vec_index += 1
601
-
602
- # if the user selects modify search parameters, go through and check to see if each one has the number of targets that the user wanted
603
- # if not, append from the deletedDict until they do
604
- if self.modifyParamscheckBox.isChecked():
605
- for gene in self.Output:
606
- if len(self.Output[gene]) < num_targets_per_gene:
607
- for i in range(len(deletedDict[gene])):
608
- if len(self.Output[gene]) == num_targets_per_gene:
609
- break
610
- else:
611
- loc = deletedDict[gene][i][0]
612
- seq = deletedDict[gene][i][1]
613
- pam = deletedDict[gene][i][2]
614
- score = deletedDict[gene][i][3]
615
- strand = deletedDict[gene][i][4] + '*'
616
- endo = deletedDict[gene][i][5]
617
- self.Output[gene].append((loc, seq, pam, score, strand, endo))
618
-
619
- # Now output to the file
620
- try:
621
- f = open(output_file, 'w')
622
- # if OT checked
623
- if self.find_off_Checkbox.isChecked():
624
- f.write('Gene Name,Sequence,On-Target Score,Off-Target Score,Location,PAM,Strand\n')
625
- elif not self.find_off_Checkbox.isChecked():
626
- f.write('Gene Name,Sequence,On-Target Score,Location,PAM,Strand\n')
627
-
628
- for gene in self.Output:
629
- i = 0
630
- gene_name = self.gen_lib_dict[gene][-1]
631
- for target in self.Output[gene]:
632
- # check to see if the target did not match the user's parameters and they selected 'modify'
633
- # if the target has an error, put 2 asterisks in front of the target sequence
634
- if '*' in target[4]:
635
- tag_id = "**" + gene_name + "-" + str(i + 1)
636
- else:
637
- tag_id = gene_name + "-" + str(i + 1)
638
- i += 1
639
-
640
- tag_id = tag_id.replace(',', '')
641
-
642
- # if OT checked
643
- if self.find_off_Checkbox.isChecked():
644
- f.write(tag_id + ',' + target[1] + ',' + str(target[3]) + ',' + str(target[5]) + ',' + str(abs(int(target[0]))) + ',' + target[2] + ',' + target[4][0] + '\n')
645
- # if OT not checked
646
- elif not self.find_off_Checkbox.isChecked():
647
- f.write(tag_id + ',' + target[1] + ',' + str(target[3]) + ',' + str(abs(int(target[0]))) + ',' + target[2] + ',' + target[4][0] + '\n')
648
-
649
- f.close()
650
- except PermissionError:
651
- show_message(
652
- fontSize=12,
653
- icon=QtWidgets.QMessageBox.Icon.Critical,
654
- title="File Cannot Open",
655
- message="This file cannot be opened. Please make sure that the file is not opened elsewhere and try again."
656
- )
657
- return -1
658
- except Exception as e:
659
- print(e)
660
- return
661
- except Exception as e:
662
- show_error("Error in generate() in generate library.", e)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/genomeBrowser.py DELETED
@@ -1,154 +0,0 @@
1
- import sys, os
2
- import models.GlobalSettings as GlobalSettings
3
- from PyQt5 import QtWidgets, uic, QtGui, QtCore, Qt
4
- import PyQt5.QtWebEngineWidgets
5
- from PyQt5.QtWidgets import QApplication
6
- from PyQt5.QtWebEngineWidgets import QWebEngineView
7
- from PyQt5.QtCore import QDir, QUrl
8
- from Bio import Entrez, SeqIO
9
- import PyQt5.QtNetwork as QtNetwork
10
- import platform
11
- import glob
12
- import ssl
13
- import traceback
14
- import webbrowser
15
- from utils.ui import show_error
16
-
17
- logger = GlobalSettings.logger
18
-
19
- ssl._create_default_https_context = ssl._create_unverified_context
20
-
21
- class WebEnginePage(PyQt5.QtWebEngineWidgets.QWebEnginePage):
22
- def certificateError(self, certificateError):
23
- print("ssl error")
24
-
25
- class genomebrowser(QtWidgets.QWidget):
26
- def __init__(self, parent=None):
27
- try:
28
- default_config = QtNetwork.QSslConfiguration.defaultConfiguration()
29
- default_config.setProtocol(QtNetwork.QSsl.TlsV1_2)
30
- QtNetwork.QSslConfiguration.setDefaultConfiguration(default_config)
31
- except Exception as e:
32
- show_error("Error initializing genomebrowser class.", e)
33
-
34
- def splitStringNCBI(self, longString):
35
- try:
36
- return (longString).split(':')[2]
37
- except:
38
- pass
39
-
40
- def splitStringLocal(self, longString):
41
- try:
42
- return (longString.split('/').pop()).split('.')[0]
43
- except:
44
- pass
45
-
46
- def ncbiAPI(self, filename):
47
- try:
48
- if platform.system() == 'Windows':
49
- filename = str(filename).replace("/","\\")
50
-
51
- genomeList = []
52
- for gb_record in SeqIO.parse(open(filename, "r"), "genbank"):
53
- genomeList.append(gb_record.id)
54
-
55
- return genomeList
56
-
57
- except Exception as e:
58
- show_error("Error in ncbiAPI() in genomebrowser.", e)
59
-
60
- def createHtml(self, genomeList):
61
- try:
62
- htmlString1 = """
63
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
64
- <ihtml>
65
- <head>
66
- <title>NCBI Sequence Viewer - programmatic initialization</title>
67
- <script type="text/javascript" src="https://www.ncbi.nlm.nih.gov/projects/sviewer/js/sviewer.js"></script>
68
- <script>
69
- function loadSV(id) {
70
- var svapp = SeqView.App.findAppByDivId("mySeqViewer1");
71
- if (!svapp)
72
- svapp = new SeqView.App("mySeqViewer1");
73
- params = 'appname=UniversityofTennesseeCasper&amp;id=' + id;
74
- svapp.reload(params);
75
- }
76
- </script>
77
- </head>
78
- <body>
79
- Select a chromosome from the list:<br/>
80
-
81
- <select onchange="loadSV(event.target.value);">
82
- <option value="">-</option>
83
- """
84
-
85
- htmlString2 = """
86
- <option value="{}">Chromosome {}</option>
87
- """
88
-
89
- htmlString3 = """
90
- </select>
91
- <br/>
92
-
93
- <div id="mySeqViewer1" class="SeqViewerApp" data-autoload>
94
- <a href="?embedded=true&appname=testapp1&id={}"></a>
95
- </div>
96
-
97
- </body>
98
- </html>
99
- """.format(genomeList[0])
100
-
101
- # Find file path for template
102
- # seek to beginning and truncate
103
- genomeBrowserTemplateFilePath = GlobalSettings.appdir + "genomeBrowserTemplate.html"
104
- raw = open(genomeBrowserTemplateFilePath, "r+")
105
- raw.seek(0)
106
- raw.truncate()
107
-
108
- #write the 3 part string format
109
- raw.write(htmlString1)
110
-
111
- for index,genome in enumerate(genomeList):
112
- raw.write(htmlString2.format(genome,index+1))
113
-
114
- raw.write(htmlString3)
115
- except Exception as e:
116
- show_error("Error in createHtml() in genomebrowser.", e)
117
-
118
- def createGraph(self, p):
119
- try:
120
- selectedGenome = p.annotation_files.currentText()
121
- print(selectedGenome)
122
- gciVariable = self.splitStringLocal(selectedGenome)
123
- print(gciVariable)
124
-
125
- if(gciVariable == None):
126
- return
127
-
128
- fileToSearch = GlobalSettings.mainWindow.annotation_files.currentText()
129
- for file in glob.glob(GlobalSettings.CSPR_DB + "/**/*.gb*", recursive=True):
130
- if file.find(fileToSearch) != -1:
131
- fileToSearch = file
132
- break
133
-
134
- if(str(fileToSearch).find(".gb") == -1):
135
- QtWidgets.QMessageBox.information(p, "Genomebrowser Error", "Filetype must be GenBank format.", QtWidgets.QMessageBox.Ok)
136
- return
137
-
138
-
139
- try:
140
- genomeList = self.ncbiAPI(fileToSearch)
141
- except:
142
- QtWidgets.QMessageBox.question(p, "GenBank_FileNotFound", "GenBank file is not in selected directory", QtWidgets.QMessageBox.Ok)
143
- return
144
-
145
- self.createHtml(genomeList)
146
- self.browser = QWebEngineView()
147
-
148
- file_path = GlobalSettings.appdir + "genomeBrowserTemplate.html"
149
- if platform.system() == "Darwin":
150
- file_path = "file:///"+file_path
151
- ### Add logic for Linux ?
152
- webbrowser.open(file_path, new=2)
153
- except Exception as e:
154
- show_error("Error in createGraph() in genomebrowser.", e)